File: | polly/lib/External/isl/isl_map_simplify.c |
Warning: | line 671, column 41 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||||||||||
2 | * Copyright 2008-2009 Katholieke Universiteit Leuven | ||||||||||||
3 | * Copyright 2012-2013 Ecole Normale Superieure | ||||||||||||
4 | * Copyright 2014-2015 INRIA Rocquencourt | ||||||||||||
5 | * Copyright 2016 Sven Verdoolaege | ||||||||||||
6 | * | ||||||||||||
7 | * Use of this software is governed by the MIT license | ||||||||||||
8 | * | ||||||||||||
9 | * Written by Sven Verdoolaege, K.U.Leuven, Departement | ||||||||||||
10 | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium | ||||||||||||
11 | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France | ||||||||||||
12 | * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, | ||||||||||||
13 | * B.P. 105 - 78153 Le Chesnay, France | ||||||||||||
14 | */ | ||||||||||||
15 | |||||||||||||
16 | #include <isl_ctx_private.h> | ||||||||||||
17 | #include <isl_map_private.h> | ||||||||||||
18 | #include "isl_equalities.h" | ||||||||||||
19 | #include <isl/map.h> | ||||||||||||
20 | #include <isl_seq.h> | ||||||||||||
21 | #include "isl_tab.h" | ||||||||||||
22 | #include <isl_space_private.h> | ||||||||||||
23 | #include <isl_mat_private.h> | ||||||||||||
24 | #include <isl_vec_private.h> | ||||||||||||
25 | |||||||||||||
26 | #include <bset_to_bmap.c> | ||||||||||||
27 | #include <bset_from_bmap.c> | ||||||||||||
28 | #include <set_to_map.c> | ||||||||||||
29 | #include <set_from_map.c> | ||||||||||||
30 | |||||||||||||
31 | static void swap_equality(struct isl_basic_map *bmap, int a, int b) | ||||||||||||
32 | { | ||||||||||||
33 | isl_int *t = bmap->eq[a]; | ||||||||||||
34 | bmap->eq[a] = bmap->eq[b]; | ||||||||||||
35 | bmap->eq[b] = t; | ||||||||||||
36 | } | ||||||||||||
37 | |||||||||||||
38 | static void swap_inequality(struct isl_basic_map *bmap, int a, int b) | ||||||||||||
39 | { | ||||||||||||
40 | if (a != b) { | ||||||||||||
41 | isl_int *t = bmap->ineq[a]; | ||||||||||||
42 | bmap->ineq[a] = bmap->ineq[b]; | ||||||||||||
43 | bmap->ineq[b] = t; | ||||||||||||
44 | } | ||||||||||||
45 | } | ||||||||||||
46 | |||||||||||||
47 | __isl_give isl_basic_map *isl_basic_map_normalize_constraints( | ||||||||||||
48 | __isl_take isl_basic_map *bmap) | ||||||||||||
49 | { | ||||||||||||
50 | int i; | ||||||||||||
51 | isl_int gcd; | ||||||||||||
52 | unsigned total = isl_basic_map_total_dim(bmap); | ||||||||||||
53 | |||||||||||||
54 | if (!bmap) | ||||||||||||
55 | return NULL((void*)0); | ||||||||||||
56 | |||||||||||||
57 | isl_int_init(gcd)isl_sioimath_init((gcd)); | ||||||||||||
58 | for (i = bmap->n_eq - 1; i >= 0; --i) { | ||||||||||||
59 | isl_seq_gcd(bmap->eq[i]+1, total, &gcd); | ||||||||||||
60 | if (isl_int_is_zero(gcd)(isl_sioimath_sgn(*(gcd)) == 0)) { | ||||||||||||
61 | if (!isl_int_is_zero(bmap->eq[i][0])(isl_sioimath_sgn(*(bmap->eq[i][0])) == 0)) { | ||||||||||||
62 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
63 | break; | ||||||||||||
64 | } | ||||||||||||
65 | isl_basic_map_drop_equality(bmap, i); | ||||||||||||
66 | continue; | ||||||||||||
67 | } | ||||||||||||
68 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)(!!(((bmap)->flags) & ((1 << 4))))) | ||||||||||||
69 | isl_int_gcd(gcd, gcd, bmap->eq[i][0])isl_sioimath_gcd((gcd), *(gcd), *(bmap->eq[i][0])); | ||||||||||||
70 | if (isl_int_is_one(gcd)(isl_sioimath_cmp_si(*(gcd), 1) == 0)) | ||||||||||||
71 | continue; | ||||||||||||
72 | if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)isl_sioimath_is_divisible_by(*(bmap->eq[i][0]), *(gcd))) { | ||||||||||||
73 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
74 | break; | ||||||||||||
75 | } | ||||||||||||
76 | isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total); | ||||||||||||
77 | } | ||||||||||||
78 | |||||||||||||
79 | for (i = bmap->n_ineq - 1; i >= 0; --i) { | ||||||||||||
80 | isl_seq_gcd(bmap->ineq[i]+1, total, &gcd); | ||||||||||||
81 | if (isl_int_is_zero(gcd)(isl_sioimath_sgn(*(gcd)) == 0)) { | ||||||||||||
82 | if (isl_int_is_neg(bmap->ineq[i][0])(isl_sioimath_sgn(*(bmap->ineq[i][0])) < 0)) { | ||||||||||||
83 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
84 | break; | ||||||||||||
85 | } | ||||||||||||
86 | isl_basic_map_drop_inequality(bmap, i); | ||||||||||||
87 | continue; | ||||||||||||
88 | } | ||||||||||||
89 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)(!!(((bmap)->flags) & ((1 << 4))))) | ||||||||||||
90 | isl_int_gcd(gcd, gcd, bmap->ineq[i][0])isl_sioimath_gcd((gcd), *(gcd), *(bmap->ineq[i][0])); | ||||||||||||
91 | if (isl_int_is_one(gcd)(isl_sioimath_cmp_si(*(gcd), 1) == 0)) | ||||||||||||
92 | continue; | ||||||||||||
93 | isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd)isl_sioimath_fdiv_q((bmap->ineq[i][0]), *(bmap->ineq[i] [0]), *(gcd)); | ||||||||||||
94 | isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total); | ||||||||||||
95 | } | ||||||||||||
96 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); | ||||||||||||
97 | |||||||||||||
98 | return bmap; | ||||||||||||
99 | } | ||||||||||||
100 | |||||||||||||
101 | __isl_give isl_basic_setisl_basic_map *isl_basic_set_normalize_constraints( | ||||||||||||
102 | __isl_take isl_basic_setisl_basic_map *bset) | ||||||||||||
103 | { | ||||||||||||
104 | isl_basic_map *bmap = bset_to_bmap(bset); | ||||||||||||
105 | return bset_from_bmap(isl_basic_map_normalize_constraints(bmap)); | ||||||||||||
106 | } | ||||||||||||
107 | |||||||||||||
108 | /* Reduce the coefficient of the variable at position "pos" | ||||||||||||
109 | * in integer division "div", such that it lies in the half-open | ||||||||||||
110 | * interval (1/2,1/2], extracting any excess value from this integer division. | ||||||||||||
111 | * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0 | ||||||||||||
112 | * corresponds to the constant term. | ||||||||||||
113 | * | ||||||||||||
114 | * That is, the integer division is of the form | ||||||||||||
115 | * | ||||||||||||
116 | * floor((... + (c * d + r) * x_pos + ...)/d) | ||||||||||||
117 | * | ||||||||||||
118 | * with -d < 2 * r <= d. | ||||||||||||
119 | * Replace it by | ||||||||||||
120 | * | ||||||||||||
121 | * floor((... + r * x_pos + ...)/d) + c * x_pos | ||||||||||||
122 | * | ||||||||||||
123 | * If 2 * ((c * d + r) % d) <= d, then c = floor((c * d + r)/d). | ||||||||||||
124 | * Otherwise, c = floor((c * d + r)/d) + 1. | ||||||||||||
125 | * | ||||||||||||
126 | * This is the same normalization that is performed by isl_aff_floor. | ||||||||||||
127 | */ | ||||||||||||
128 | static __isl_give isl_basic_map *reduce_coefficient_in_div( | ||||||||||||
129 | __isl_take isl_basic_map *bmap, int div, int pos) | ||||||||||||
130 | { | ||||||||||||
131 | isl_int shift; | ||||||||||||
132 | int add_one; | ||||||||||||
133 | |||||||||||||
134 | isl_int_init(shift)isl_sioimath_init((shift)); | ||||||||||||
135 | isl_int_fdiv_r(shift, bmap->div[div][1 + pos], bmap->div[div][0])isl_sioimath_fdiv_r((shift), *(bmap->div[div][1 + pos]), * (bmap->div[div][0])); | ||||||||||||
136 | isl_int_mul_ui(shift, shift, 2)isl_sioimath_mul_ui((shift), *(shift), 2); | ||||||||||||
137 | add_one = isl_int_gt(shift, bmap->div[div][0])(isl_sioimath_cmp(*(shift), *(bmap->div[div][0])) > 0); | ||||||||||||
138 | isl_int_fdiv_q(shift, bmap->div[div][1 + pos], bmap->div[div][0])isl_sioimath_fdiv_q((shift), *(bmap->div[div][1 + pos]), * (bmap->div[div][0])); | ||||||||||||
139 | if (add_one) | ||||||||||||
140 | isl_int_add_ui(shift, shift, 1)isl_sioimath_add_ui((shift), *(shift), 1); | ||||||||||||
141 | isl_int_neg(shift, shift)isl_sioimath_neg((shift), *(shift)); | ||||||||||||
142 | bmap = isl_basic_map_shift_div(bmap, div, pos, shift); | ||||||||||||
143 | isl_int_clear(shift)isl_sioimath_clear((shift)); | ||||||||||||
144 | |||||||||||||
145 | return bmap; | ||||||||||||
146 | } | ||||||||||||
147 | |||||||||||||
148 | /* Does the coefficient of the variable at position "pos" | ||||||||||||
149 | * in integer division "div" need to be reduced? | ||||||||||||
150 | * That is, does it lie outside the half-open interval (1/2,1/2]? | ||||||||||||
151 | * The coefficient c/d lies outside this interval if abs(2 * c) >= d and | ||||||||||||
152 | * 2 * c != d. | ||||||||||||
153 | */ | ||||||||||||
154 | static isl_bool needs_reduction(__isl_keep isl_basic_map *bmap, int div, | ||||||||||||
155 | int pos) | ||||||||||||
156 | { | ||||||||||||
157 | isl_bool r; | ||||||||||||
158 | |||||||||||||
159 | if (isl_int_is_zero(bmap->div[div][1 + pos])(isl_sioimath_sgn(*(bmap->div[div][1 + pos])) == 0)) | ||||||||||||
160 | return isl_bool_false; | ||||||||||||
161 | |||||||||||||
162 | isl_int_mul_ui(bmap->div[div][1 + pos], bmap->div[div][1 + pos], 2)isl_sioimath_mul_ui((bmap->div[div][1 + pos]), *(bmap-> div[div][1 + pos]), 2); | ||||||||||||
163 | r = isl_int_abs_ge(bmap->div[div][1 + pos], bmap->div[div][0])(isl_sioimath_abs_cmp(*(bmap->div[div][1 + pos]), *(bmap-> div[div][0])) >= 0) && | ||||||||||||
164 | !isl_int_eq(bmap->div[div][1 + pos], bmap->div[div][0])(isl_sioimath_cmp(*(bmap->div[div][1 + pos]), *(bmap->div [div][0])) == 0); | ||||||||||||
165 | isl_int_divexact_ui(bmap->div[div][1 + pos],isl_sioimath_tdiv_q_ui((bmap->div[div][1 + pos]), *(bmap-> div[div][1 + pos]), 2) | ||||||||||||
166 | bmap->div[div][1 + pos], 2)isl_sioimath_tdiv_q_ui((bmap->div[div][1 + pos]), *(bmap-> div[div][1 + pos]), 2); | ||||||||||||
167 | |||||||||||||
168 | return r; | ||||||||||||
169 | } | ||||||||||||
170 | |||||||||||||
171 | /* Reduce the coefficients (including the constant term) of | ||||||||||||
172 | * integer division "div", if needed. | ||||||||||||
173 | * In particular, make sure all coefficients lie in | ||||||||||||
174 | * the half-open interval (1/2,1/2]. | ||||||||||||
175 | */ | ||||||||||||
176 | static __isl_give isl_basic_map *reduce_div_coefficients_of_div( | ||||||||||||
177 | __isl_take isl_basic_map *bmap, int div) | ||||||||||||
178 | { | ||||||||||||
179 | int i; | ||||||||||||
180 | unsigned total = 1 + isl_basic_map_total_dim(bmap); | ||||||||||||
181 | |||||||||||||
182 | for (i = 0; i < total; ++i) { | ||||||||||||
183 | isl_bool reduce; | ||||||||||||
184 | |||||||||||||
185 | reduce = needs_reduction(bmap, div, i); | ||||||||||||
186 | if (reduce < 0) | ||||||||||||
187 | return isl_basic_map_free(bmap); | ||||||||||||
188 | if (!reduce) | ||||||||||||
189 | continue; | ||||||||||||
190 | bmap = reduce_coefficient_in_div(bmap, div, i); | ||||||||||||
191 | if (!bmap) | ||||||||||||
192 | break; | ||||||||||||
193 | } | ||||||||||||
194 | |||||||||||||
195 | return bmap; | ||||||||||||
196 | } | ||||||||||||
197 | |||||||||||||
198 | /* Reduce the coefficients (including the constant term) of | ||||||||||||
199 | * the known integer divisions, if needed | ||||||||||||
200 | * In particular, make sure all coefficients lie in | ||||||||||||
201 | * the half-open interval (1/2,1/2]. | ||||||||||||
202 | */ | ||||||||||||
203 | static __isl_give isl_basic_map *reduce_div_coefficients( | ||||||||||||
204 | __isl_take isl_basic_map *bmap) | ||||||||||||
205 | { | ||||||||||||
206 | int i; | ||||||||||||
207 | |||||||||||||
208 | if (!bmap) | ||||||||||||
209 | return NULL((void*)0); | ||||||||||||
210 | if (bmap->n_div == 0) | ||||||||||||
211 | return bmap; | ||||||||||||
212 | |||||||||||||
213 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
214 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
215 | continue; | ||||||||||||
216 | bmap = reduce_div_coefficients_of_div(bmap, i); | ||||||||||||
217 | if (!bmap) | ||||||||||||
218 | break; | ||||||||||||
219 | } | ||||||||||||
220 | |||||||||||||
221 | return bmap; | ||||||||||||
222 | } | ||||||||||||
223 | |||||||||||||
224 | /* Remove any common factor in numerator and denominator of the div expression, | ||||||||||||
225 | * not taking into account the constant term. | ||||||||||||
226 | * That is, if the div is of the form | ||||||||||||
227 | * | ||||||||||||
228 | * floor((a + m f(x))/(m d)) | ||||||||||||
229 | * | ||||||||||||
230 | * then replace it by | ||||||||||||
231 | * | ||||||||||||
232 | * floor((floor(a/m) + f(x))/d) | ||||||||||||
233 | * | ||||||||||||
234 | * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d | ||||||||||||
235 | * and can therefore not influence the result of the floor. | ||||||||||||
236 | */ | ||||||||||||
237 | static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div) | ||||||||||||
238 | { | ||||||||||||
239 | unsigned total = isl_basic_map_total_dim(bmap); | ||||||||||||
240 | isl_ctx *ctx = bmap->ctx; | ||||||||||||
241 | |||||||||||||
242 | if (isl_int_is_zero(bmap->div[div][0])(isl_sioimath_sgn(*(bmap->div[div][0])) == 0)) | ||||||||||||
243 | return; | ||||||||||||
244 | isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd); | ||||||||||||
245 | isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0])isl_sioimath_gcd((ctx->normalize_gcd), *(ctx->normalize_gcd ), *(bmap->div[div][0])); | ||||||||||||
246 | if (isl_int_is_one(ctx->normalize_gcd)(isl_sioimath_cmp_si(*(ctx->normalize_gcd), 1) == 0)) | ||||||||||||
247 | return; | ||||||||||||
248 | isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],isl_sioimath_fdiv_q((bmap->div[div][1]), *(bmap->div[div ][1]), *(ctx->normalize_gcd)) | ||||||||||||
249 | ctx->normalize_gcd)isl_sioimath_fdiv_q((bmap->div[div][1]), *(bmap->div[div ][1]), *(ctx->normalize_gcd)); | ||||||||||||
250 | isl_int_divexact(bmap->div[div][0], bmap->div[div][0],isl_sioimath_tdiv_q((bmap->div[div][0]), *(bmap->div[div ][0]), *(ctx->normalize_gcd)) | ||||||||||||
251 | ctx->normalize_gcd)isl_sioimath_tdiv_q((bmap->div[div][0]), *(bmap->div[div ][0]), *(ctx->normalize_gcd)); | ||||||||||||
252 | isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2, | ||||||||||||
253 | ctx->normalize_gcd, total); | ||||||||||||
254 | } | ||||||||||||
255 | |||||||||||||
256 | /* Remove any common factor in numerator and denominator of a div expression, | ||||||||||||
257 | * not taking into account the constant term. | ||||||||||||
258 | * That is, look for any div of the form | ||||||||||||
259 | * | ||||||||||||
260 | * floor((a + m f(x))/(m d)) | ||||||||||||
261 | * | ||||||||||||
262 | * and replace it by | ||||||||||||
263 | * | ||||||||||||
264 | * floor((floor(a/m) + f(x))/d) | ||||||||||||
265 | * | ||||||||||||
266 | * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d | ||||||||||||
267 | * and can therefore not influence the result of the floor. | ||||||||||||
268 | */ | ||||||||||||
269 | static __isl_give isl_basic_map *normalize_div_expressions( | ||||||||||||
270 | __isl_take isl_basic_map *bmap) | ||||||||||||
271 | { | ||||||||||||
272 | int i; | ||||||||||||
273 | |||||||||||||
274 | if (!bmap) | ||||||||||||
275 | return NULL((void*)0); | ||||||||||||
276 | if (bmap->n_div == 0) | ||||||||||||
277 | return bmap; | ||||||||||||
278 | |||||||||||||
279 | for (i = 0; i < bmap->n_div; ++i) | ||||||||||||
280 | normalize_div_expression(bmap, i); | ||||||||||||
281 | |||||||||||||
282 | return bmap; | ||||||||||||
283 | } | ||||||||||||
284 | |||||||||||||
285 | /* Assumes divs have been ordered if keep_divs is set. | ||||||||||||
286 | */ | ||||||||||||
287 | static void eliminate_var_using_equality(struct isl_basic_map *bmap, | ||||||||||||
288 | unsigned pos, isl_int *eq, int keep_divs, int *progress) | ||||||||||||
289 | { | ||||||||||||
290 | unsigned total; | ||||||||||||
291 | unsigned space_total; | ||||||||||||
292 | int k; | ||||||||||||
293 | int last_div; | ||||||||||||
294 | |||||||||||||
295 | total = isl_basic_map_total_dim(bmap); | ||||||||||||
296 | space_total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
297 | last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div); | ||||||||||||
298 | for (k = 0; k < bmap->n_eq; ++k) { | ||||||||||||
299 | if (bmap->eq[k] == eq) | ||||||||||||
300 | continue; | ||||||||||||
301 | if (isl_int_is_zero(bmap->eq[k][1+pos])(isl_sioimath_sgn(*(bmap->eq[k][1+pos])) == 0)) | ||||||||||||
302 | continue; | ||||||||||||
303 | if (progress) | ||||||||||||
304 | *progress = 1; | ||||||||||||
305 | isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL((void*)0)); | ||||||||||||
306 | isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total); | ||||||||||||
307 | } | ||||||||||||
308 | |||||||||||||
309 | for (k = 0; k < bmap->n_ineq; ++k) { | ||||||||||||
310 | if (isl_int_is_zero(bmap->ineq[k][1+pos])(isl_sioimath_sgn(*(bmap->ineq[k][1+pos])) == 0)) | ||||||||||||
311 | continue; | ||||||||||||
312 | if (progress) | ||||||||||||
313 | *progress = 1; | ||||||||||||
314 | isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL((void*)0)); | ||||||||||||
315 | isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total); | ||||||||||||
316 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED)(((bmap)->flags) &= ~((1 << 5))); | ||||||||||||
317 | } | ||||||||||||
318 | |||||||||||||
319 | for (k = 0; k < bmap->n_div; ++k) { | ||||||||||||
320 | if (isl_int_is_zero(bmap->div[k][0])(isl_sioimath_sgn(*(bmap->div[k][0])) == 0)) | ||||||||||||
321 | continue; | ||||||||||||
322 | if (isl_int_is_zero(bmap->div[k][1+1+pos])(isl_sioimath_sgn(*(bmap->div[k][1+1+pos])) == 0)) | ||||||||||||
323 | continue; | ||||||||||||
324 | if (progress) | ||||||||||||
325 | *progress = 1; | ||||||||||||
326 | /* We need to be careful about circular definitions, | ||||||||||||
327 | * so for now we just remove the definition of div k | ||||||||||||
328 | * if the equality contains any divs. | ||||||||||||
329 | * If keep_divs is set, then the divs have been ordered | ||||||||||||
330 | * and we can keep the definition as long as the result | ||||||||||||
331 | * is still ordered. | ||||||||||||
332 | */ | ||||||||||||
333 | if (last_div == -1 || (keep_divs && last_div < k)) { | ||||||||||||
334 | isl_seq_elim(bmap->div[k]+1, eq, | ||||||||||||
335 | 1+pos, 1+total, &bmap->div[k][0]); | ||||||||||||
336 | normalize_div_expression(bmap, k); | ||||||||||||
337 | } else | ||||||||||||
338 | isl_seq_clr(bmap->div[k], 1 + total); | ||||||||||||
339 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED)(((bmap)->flags) &= ~((1 << 5))); | ||||||||||||
340 | } | ||||||||||||
341 | } | ||||||||||||
342 | |||||||||||||
343 | /* Assumes divs have been ordered if keep_divs is set. | ||||||||||||
344 | */ | ||||||||||||
345 | static __isl_give isl_basic_map *eliminate_div(__isl_take isl_basic_map *bmap, | ||||||||||||
346 | isl_int *eq, unsigned div, int keep_divs) | ||||||||||||
347 | { | ||||||||||||
348 | unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div; | ||||||||||||
349 | |||||||||||||
350 | eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL((void*)0)); | ||||||||||||
351 | |||||||||||||
352 | bmap = isl_basic_map_drop_div(bmap, div); | ||||||||||||
353 | |||||||||||||
354 | return bmap; | ||||||||||||
355 | } | ||||||||||||
356 | |||||||||||||
357 | /* Check if elimination of div "div" using equality "eq" would not | ||||||||||||
358 | * result in a div depending on a later div. | ||||||||||||
359 | */ | ||||||||||||
360 | static isl_bool ok_to_eliminate_div(__isl_keep isl_basic_map *bmap, isl_int *eq, | ||||||||||||
361 | unsigned div) | ||||||||||||
362 | { | ||||||||||||
363 | int k; | ||||||||||||
364 | int last_div; | ||||||||||||
365 | unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
366 | unsigned pos = space_total + div; | ||||||||||||
367 | |||||||||||||
368 | last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div); | ||||||||||||
369 | if (last_div < 0 || last_div <= div) | ||||||||||||
370 | return isl_bool_true; | ||||||||||||
371 | |||||||||||||
372 | for (k = 0; k <= last_div; ++k) { | ||||||||||||
373 | if (isl_int_is_zero(bmap->div[k][0])(isl_sioimath_sgn(*(bmap->div[k][0])) == 0)) | ||||||||||||
374 | continue; | ||||||||||||
375 | if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos])(isl_sioimath_sgn(*(bmap->div[k][1 + 1 + pos])) == 0)) | ||||||||||||
376 | return isl_bool_false; | ||||||||||||
377 | } | ||||||||||||
378 | |||||||||||||
379 | return isl_bool_true; | ||||||||||||
380 | } | ||||||||||||
381 | |||||||||||||
382 | /* Eliminate divs based on equalities | ||||||||||||
383 | */ | ||||||||||||
384 | static __isl_give isl_basic_map *eliminate_divs_eq( | ||||||||||||
385 | __isl_take isl_basic_map *bmap, int *progress) | ||||||||||||
386 | { | ||||||||||||
387 | int d; | ||||||||||||
388 | int i; | ||||||||||||
389 | int modified = 0; | ||||||||||||
390 | unsigned off; | ||||||||||||
391 | |||||||||||||
392 | bmap = isl_basic_map_order_divs(bmap); | ||||||||||||
393 | |||||||||||||
394 | if (!bmap) | ||||||||||||
395 | return NULL((void*)0); | ||||||||||||
396 | |||||||||||||
397 | off = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
398 | |||||||||||||
399 | for (d = bmap->n_div - 1; d >= 0 ; --d) { | ||||||||||||
400 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
401 | isl_bool ok; | ||||||||||||
402 | |||||||||||||
403 | if (!isl_int_is_one(bmap->eq[i][off + d])(isl_sioimath_cmp_si(*(bmap->eq[i][off + d]), 1) == 0) && | ||||||||||||
404 | !isl_int_is_negone(bmap->eq[i][off + d])(isl_sioimath_cmp_si(*(bmap->eq[i][off + d]), -1) == 0)) | ||||||||||||
405 | continue; | ||||||||||||
406 | ok = ok_to_eliminate_div(bmap, bmap->eq[i], d); | ||||||||||||
407 | if (ok < 0) | ||||||||||||
408 | return isl_basic_map_free(bmap); | ||||||||||||
409 | if (!ok) | ||||||||||||
410 | continue; | ||||||||||||
411 | modified = 1; | ||||||||||||
412 | *progress = 1; | ||||||||||||
413 | bmap = eliminate_div(bmap, bmap->eq[i], d, 1); | ||||||||||||
414 | if (isl_basic_map_drop_equality(bmap, i) < 0) | ||||||||||||
415 | return isl_basic_map_free(bmap); | ||||||||||||
416 | break; | ||||||||||||
417 | } | ||||||||||||
418 | } | ||||||||||||
419 | if (modified) | ||||||||||||
420 | return eliminate_divs_eq(bmap, progress); | ||||||||||||
421 | return bmap; | ||||||||||||
422 | } | ||||||||||||
423 | |||||||||||||
424 | /* Eliminate divs based on inequalities | ||||||||||||
425 | */ | ||||||||||||
426 | static __isl_give isl_basic_map *eliminate_divs_ineq( | ||||||||||||
427 | __isl_take isl_basic_map *bmap, int *progress) | ||||||||||||
428 | { | ||||||||||||
429 | int d; | ||||||||||||
430 | int i; | ||||||||||||
431 | unsigned off; | ||||||||||||
432 | struct isl_ctx *ctx; | ||||||||||||
433 | |||||||||||||
434 | if (!bmap) | ||||||||||||
435 | return NULL((void*)0); | ||||||||||||
436 | |||||||||||||
437 | ctx = bmap->ctx; | ||||||||||||
438 | off = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
439 | |||||||||||||
440 | for (d = bmap->n_div - 1; d >= 0 ; --d) { | ||||||||||||
441 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
442 | if (!isl_int_is_zero(bmap->eq[i][off + d])(isl_sioimath_sgn(*(bmap->eq[i][off + d])) == 0)) | ||||||||||||
443 | break; | ||||||||||||
444 | if (i < bmap->n_eq) | ||||||||||||
445 | continue; | ||||||||||||
446 | for (i = 0; i < bmap->n_ineq; ++i) | ||||||||||||
447 | if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one)(isl_sioimath_abs_cmp(*(bmap->ineq[i][off + d]), *(ctx-> one)) > 0)) | ||||||||||||
448 | break; | ||||||||||||
449 | if (i < bmap->n_ineq) | ||||||||||||
450 | continue; | ||||||||||||
451 | *progress = 1; | ||||||||||||
452 | bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1); | ||||||||||||
453 | if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)(!!(((bmap)->flags) & ((1 << 1))))) | ||||||||||||
454 | break; | ||||||||||||
455 | bmap = isl_basic_map_drop_div(bmap, d); | ||||||||||||
456 | if (!bmap) | ||||||||||||
457 | break; | ||||||||||||
458 | } | ||||||||||||
459 | return bmap; | ||||||||||||
460 | } | ||||||||||||
461 | |||||||||||||
462 | /* Does the equality constraint at position "eq" in "bmap" involve | ||||||||||||
463 | * any local variables in the range [first, first + n) | ||||||||||||
464 | * that are not marked as having an explicit representation? | ||||||||||||
465 | */ | ||||||||||||
466 | static isl_bool bmap_eq_involves_unknown_divs(__isl_keep isl_basic_map *bmap, | ||||||||||||
467 | int eq, unsigned first, unsigned n) | ||||||||||||
468 | { | ||||||||||||
469 | unsigned o_div; | ||||||||||||
470 | int i; | ||||||||||||
471 | |||||||||||||
472 | if (!bmap) | ||||||||||||
473 | return isl_bool_error; | ||||||||||||
474 | |||||||||||||
475 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
476 | for (i = 0; i < n; ++i) { | ||||||||||||
477 | isl_bool unknown; | ||||||||||||
478 | |||||||||||||
479 | if (isl_int_is_zero(bmap->eq[eq][o_div + first + i])(isl_sioimath_sgn(*(bmap->eq[eq][o_div + first + i])) == 0 )) | ||||||||||||
480 | continue; | ||||||||||||
481 | unknown = isl_basic_map_div_is_marked_unknown(bmap, first + i); | ||||||||||||
482 | if (unknown < 0) | ||||||||||||
483 | return isl_bool_error; | ||||||||||||
484 | if (unknown) | ||||||||||||
485 | return isl_bool_true; | ||||||||||||
486 | } | ||||||||||||
487 | |||||||||||||
488 | return isl_bool_false; | ||||||||||||
489 | } | ||||||||||||
490 | |||||||||||||
491 | /* The last local variable involved in the equality constraint | ||||||||||||
492 | * at position "eq" in "bmap" is the local variable at position "div". | ||||||||||||
493 | * It can therefore be used to extract an explicit representation | ||||||||||||
494 | * for that variable. | ||||||||||||
495 | * Do so unless the local variable already has an explicit representation or | ||||||||||||
496 | * the explicit representation would involve any other local variables | ||||||||||||
497 | * that in turn do not have an explicit representation. | ||||||||||||
498 | * An equality constraint involving local variables without an explicit | ||||||||||||
499 | * representation can be used in isl_basic_map_drop_redundant_divs | ||||||||||||
500 | * to separate out an independent local variable. Introducing | ||||||||||||
501 | * an explicit representation here would block this transformation, | ||||||||||||
502 | * while the partial explicit representation in itself is not very useful. | ||||||||||||
503 | * Set *progress if anything is changed. | ||||||||||||
504 | * | ||||||||||||
505 | * The equality constraint is of the form | ||||||||||||
506 | * | ||||||||||||
507 | * f(x) + n e >= 0 | ||||||||||||
508 | * | ||||||||||||
509 | * with n a positive number. The explicit representation derived from | ||||||||||||
510 | * this constraint is | ||||||||||||
511 | * | ||||||||||||
512 | * floor((-f(x))/n) | ||||||||||||
513 | */ | ||||||||||||
514 | static __isl_give isl_basic_map *set_div_from_eq(__isl_take isl_basic_map *bmap, | ||||||||||||
515 | int div, int eq, int *progress) | ||||||||||||
516 | { | ||||||||||||
517 | unsigned total, o_div; | ||||||||||||
518 | isl_bool involves; | ||||||||||||
519 | |||||||||||||
520 | if (!bmap) | ||||||||||||
521 | return NULL((void*)0); | ||||||||||||
522 | |||||||||||||
523 | if (!isl_int_is_zero(bmap->div[div][0])(isl_sioimath_sgn(*(bmap->div[div][0])) == 0)) | ||||||||||||
524 | return bmap; | ||||||||||||
525 | |||||||||||||
526 | involves = bmap_eq_involves_unknown_divs(bmap, eq, 0, div); | ||||||||||||
527 | if (involves < 0) | ||||||||||||
528 | return isl_basic_map_free(bmap); | ||||||||||||
529 | if (involves) | ||||||||||||
530 | return bmap; | ||||||||||||
531 | |||||||||||||
532 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
533 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
534 | isl_seq_neg(bmap->div[div] + 1, bmap->eq[eq], 1 + total); | ||||||||||||
535 | isl_int_set_si(bmap->div[div][1 + o_div + div], 0)isl_sioimath_set_si((bmap->div[div][1 + o_div + div]), 0); | ||||||||||||
536 | isl_int_set(bmap->div[div][0], bmap->eq[eq][o_div + div])isl_sioimath_set((bmap->div[div][0]), *(bmap->eq[eq][o_div + div])); | ||||||||||||
537 | if (progress) | ||||||||||||
538 | *progress = 1; | ||||||||||||
539 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED)(((bmap)->flags) &= ~((1 << 5))); | ||||||||||||
540 | |||||||||||||
541 | return bmap; | ||||||||||||
542 | } | ||||||||||||
543 | |||||||||||||
544 | __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap, | ||||||||||||
545 | int *progress) | ||||||||||||
546 | { | ||||||||||||
547 | int k; | ||||||||||||
548 | int done; | ||||||||||||
549 | int last_var; | ||||||||||||
550 | unsigned total_var; | ||||||||||||
551 | unsigned total; | ||||||||||||
552 | |||||||||||||
553 | bmap = isl_basic_map_order_divs(bmap); | ||||||||||||
554 | |||||||||||||
555 | if (!bmap) | ||||||||||||
556 | return NULL((void*)0); | ||||||||||||
557 | |||||||||||||
558 | total = isl_basic_map_total_dim(bmap); | ||||||||||||
559 | total_var = total - bmap->n_div; | ||||||||||||
560 | |||||||||||||
561 | last_var = total - 1; | ||||||||||||
562 | for (done = 0; done < bmap->n_eq; ++done) { | ||||||||||||
563 | for (; last_var >= 0; --last_var) { | ||||||||||||
564 | for (k = done; k < bmap->n_eq; ++k) | ||||||||||||
565 | if (!isl_int_is_zero(bmap->eq[k][1+last_var])(isl_sioimath_sgn(*(bmap->eq[k][1+last_var])) == 0)) | ||||||||||||
566 | break; | ||||||||||||
567 | if (k < bmap->n_eq) | ||||||||||||
568 | break; | ||||||||||||
569 | } | ||||||||||||
570 | if (last_var < 0) | ||||||||||||
571 | break; | ||||||||||||
572 | if (k != done) | ||||||||||||
573 | swap_equality(bmap, k, done); | ||||||||||||
574 | if (isl_int_is_neg(bmap->eq[done][1+last_var])(isl_sioimath_sgn(*(bmap->eq[done][1+last_var])) < 0)) | ||||||||||||
575 | isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total); | ||||||||||||
576 | |||||||||||||
577 | eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1, | ||||||||||||
578 | progress); | ||||||||||||
579 | |||||||||||||
580 | if (last_var >= total_var) | ||||||||||||
581 | bmap = set_div_from_eq(bmap, last_var - total_var, | ||||||||||||
582 | done, progress); | ||||||||||||
583 | if (!bmap) | ||||||||||||
584 | return NULL((void*)0); | ||||||||||||
585 | } | ||||||||||||
586 | if (done == bmap->n_eq) | ||||||||||||
587 | return bmap; | ||||||||||||
588 | for (k = done; k < bmap->n_eq; ++k) { | ||||||||||||
589 | if (isl_int_is_zero(bmap->eq[k][0])(isl_sioimath_sgn(*(bmap->eq[k][0])) == 0)) | ||||||||||||
590 | continue; | ||||||||||||
591 | return isl_basic_map_set_to_empty(bmap); | ||||||||||||
592 | } | ||||||||||||
593 | isl_basic_map_free_equality(bmap, bmap->n_eq-done); | ||||||||||||
594 | return bmap; | ||||||||||||
595 | } | ||||||||||||
596 | |||||||||||||
597 | __isl_give isl_basic_setisl_basic_map *isl_basic_set_gauss( | ||||||||||||
598 | __isl_take isl_basic_setisl_basic_map *bset, int *progress) | ||||||||||||
599 | { | ||||||||||||
600 | return bset_from_bmap(isl_basic_map_gauss(bset_to_bmap(bset), | ||||||||||||
601 | progress)); | ||||||||||||
602 | } | ||||||||||||
603 | |||||||||||||
604 | |||||||||||||
605 | static unsigned int round_up(unsigned int v) | ||||||||||||
606 | { | ||||||||||||
607 | int old_v = v; | ||||||||||||
608 | |||||||||||||
609 | while (v) { | ||||||||||||
610 | old_v = v; | ||||||||||||
611 | v ^= v & -v; | ||||||||||||
612 | } | ||||||||||||
613 | return old_v << 1; | ||||||||||||
614 | } | ||||||||||||
615 | |||||||||||||
616 | /* Hash table of inequalities in a basic map. | ||||||||||||
617 | * "index" is an array of addresses of inequalities in the basic map, some | ||||||||||||
618 | * of which are NULL. The inequalities are hashed on the coefficients | ||||||||||||
619 | * except the constant term. | ||||||||||||
620 | * "size" is the number of elements in the array and is always a power of two | ||||||||||||
621 | * "bits" is the number of bits need to represent an index into the array. | ||||||||||||
622 | * "total" is the total dimension of the basic map. | ||||||||||||
623 | */ | ||||||||||||
624 | struct isl_constraint_index { | ||||||||||||
625 | unsigned int size; | ||||||||||||
626 | int bits; | ||||||||||||
627 | isl_int ***index; | ||||||||||||
628 | unsigned total; | ||||||||||||
629 | }; | ||||||||||||
630 | |||||||||||||
631 | /* Fill in the "ci" data structure for holding the inequalities of "bmap". | ||||||||||||
632 | */ | ||||||||||||
633 | static isl_stat create_constraint_index(struct isl_constraint_index *ci, | ||||||||||||
634 | __isl_keep isl_basic_map *bmap) | ||||||||||||
635 | { | ||||||||||||
636 | isl_ctx *ctx; | ||||||||||||
637 | |||||||||||||
638 | ci->index = NULL((void*)0); | ||||||||||||
639 | if (!bmap
| ||||||||||||
640 | return isl_stat_error; | ||||||||||||
641 | ci->total = isl_basic_set_total_dim(bmap); | ||||||||||||
642 | if (bmap->n_ineq
| ||||||||||||
643 | return isl_stat_ok; | ||||||||||||
644 | ci->size = round_up(4 * (bmap->n_ineq + 1) / 3 - 1); | ||||||||||||
645 | ci->bits = ffs(ci->size) - 1; | ||||||||||||
646 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
647 | ci->index = isl_calloc_array(ctx, isl_int **, ci->size)((isl_int ** *)isl_calloc_or_die(ctx, ci->size, sizeof(isl_int **))); | ||||||||||||
648 | if (!ci->index) | ||||||||||||
649 | return isl_stat_error; | ||||||||||||
650 | |||||||||||||
651 | return isl_stat_ok; | ||||||||||||
652 | } | ||||||||||||
653 | |||||||||||||
654 | /* Free the memory allocated by create_constraint_index. | ||||||||||||
655 | */ | ||||||||||||
656 | static void constraint_index_free(struct isl_constraint_index *ci) | ||||||||||||
657 | { | ||||||||||||
658 | free(ci->index); | ||||||||||||
659 | } | ||||||||||||
660 | |||||||||||||
661 | /* Return the position in ci->index that contains the address of | ||||||||||||
662 | * an inequality that is equal to *ineq up to the constant term, | ||||||||||||
663 | * provided this address is not identical to "ineq". | ||||||||||||
664 | * If there is no such inequality, then return the position where | ||||||||||||
665 | * such an inequality should be inserted. | ||||||||||||
666 | */ | ||||||||||||
667 | static int hash_index_ineq(struct isl_constraint_index *ci, isl_int **ineq) | ||||||||||||
668 | { | ||||||||||||
669 | int h; | ||||||||||||
670 | uint32_t hash = isl_seq_get_hash_bits((*ineq) + 1, ci->total, ci->bits); | ||||||||||||
671 | for (h = hash; ci->index[h]; h = (h+1) % ci->size) | ||||||||||||
| |||||||||||||
672 | if (ineq != ci->index[h] && | ||||||||||||
673 | isl_seq_eq((*ineq) + 1, ci->index[h][0]+1, ci->total)) | ||||||||||||
674 | break; | ||||||||||||
675 | return h; | ||||||||||||
676 | } | ||||||||||||
677 | |||||||||||||
678 | /* Return the position in ci->index that contains the address of | ||||||||||||
679 | * an inequality that is equal to the k'th inequality of "bmap" | ||||||||||||
680 | * up to the constant term, provided it does not point to the very | ||||||||||||
681 | * same inequality. | ||||||||||||
682 | * If there is no such inequality, then return the position where | ||||||||||||
683 | * such an inequality should be inserted. | ||||||||||||
684 | */ | ||||||||||||
685 | static int hash_index(struct isl_constraint_index *ci, | ||||||||||||
686 | __isl_keep isl_basic_map *bmap, int k) | ||||||||||||
687 | { | ||||||||||||
688 | return hash_index_ineq(ci, &bmap->ineq[k]); | ||||||||||||
689 | } | ||||||||||||
690 | |||||||||||||
691 | static int set_hash_index(struct isl_constraint_index *ci, | ||||||||||||
692 | __isl_keep isl_basic_setisl_basic_map *bset, int k) | ||||||||||||
693 | { | ||||||||||||
694 | return hash_index(ci, bset, k); | ||||||||||||
695 | } | ||||||||||||
696 | |||||||||||||
697 | /* Fill in the "ci" data structure with the inequalities of "bset". | ||||||||||||
698 | */ | ||||||||||||
699 | static isl_stat setup_constraint_index(struct isl_constraint_index *ci, | ||||||||||||
700 | __isl_keep isl_basic_setisl_basic_map *bset) | ||||||||||||
701 | { | ||||||||||||
702 | int k, h; | ||||||||||||
703 | |||||||||||||
704 | if (create_constraint_index(ci, bset) < 0) | ||||||||||||
705 | return isl_stat_error; | ||||||||||||
706 | |||||||||||||
707 | for (k = 0; k < bset->n_ineq; ++k) { | ||||||||||||
708 | h = set_hash_index(ci, bset, k); | ||||||||||||
709 | ci->index[h] = &bset->ineq[k]; | ||||||||||||
710 | } | ||||||||||||
711 | |||||||||||||
712 | return isl_stat_ok; | ||||||||||||
713 | } | ||||||||||||
714 | |||||||||||||
715 | /* Is the inequality ineq (obviously) redundant with respect | ||||||||||||
716 | * to the constraints in "ci"? | ||||||||||||
717 | * | ||||||||||||
718 | * Look for an inequality in "ci" with the same coefficients and then | ||||||||||||
719 | * check if the contant term of "ineq" is greater than or equal | ||||||||||||
720 | * to the constant term of that inequality. If so, "ineq" is clearly | ||||||||||||
721 | * redundant. | ||||||||||||
722 | * | ||||||||||||
723 | * Note that hash_index_ineq ignores a stored constraint if it has | ||||||||||||
724 | * the same address as the passed inequality. It is ok to pass | ||||||||||||
725 | * the address of a local variable here since it will never be | ||||||||||||
726 | * the same as the address of a constraint in "ci". | ||||||||||||
727 | */ | ||||||||||||
728 | static isl_bool constraint_index_is_redundant(struct isl_constraint_index *ci, | ||||||||||||
729 | isl_int *ineq) | ||||||||||||
730 | { | ||||||||||||
731 | int h; | ||||||||||||
732 | |||||||||||||
733 | h = hash_index_ineq(ci, &ineq); | ||||||||||||
734 | if (!ci->index[h]) | ||||||||||||
735 | return isl_bool_false; | ||||||||||||
736 | return isl_int_ge(ineq[0], (*ci->index[h])[0])(isl_sioimath_cmp(*(ineq[0]), *((*ci->index[h])[0])) >= 0); | ||||||||||||
737 | } | ||||||||||||
738 | |||||||||||||
739 | /* If we can eliminate more than one div, then we need to make | ||||||||||||
740 | * sure we do it from last div to first div, in order not to | ||||||||||||
741 | * change the position of the other divs that still need to | ||||||||||||
742 | * be removed. | ||||||||||||
743 | */ | ||||||||||||
744 | static __isl_give isl_basic_map *remove_duplicate_divs( | ||||||||||||
745 | __isl_take isl_basic_map *bmap, int *progress) | ||||||||||||
746 | { | ||||||||||||
747 | unsigned int size; | ||||||||||||
748 | int *index; | ||||||||||||
749 | int *elim_for; | ||||||||||||
750 | int k, l, h; | ||||||||||||
751 | int bits; | ||||||||||||
752 | struct isl_blk eq; | ||||||||||||
753 | unsigned total_var; | ||||||||||||
754 | unsigned total; | ||||||||||||
755 | struct isl_ctx *ctx; | ||||||||||||
756 | |||||||||||||
757 | bmap = isl_basic_map_order_divs(bmap); | ||||||||||||
758 | if (!bmap || bmap->n_div <= 1) | ||||||||||||
759 | return bmap; | ||||||||||||
760 | |||||||||||||
761 | total_var = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
762 | total = total_var + bmap->n_div; | ||||||||||||
763 | |||||||||||||
764 | ctx = bmap->ctx; | ||||||||||||
765 | for (k = bmap->n_div - 1; k >= 0; --k) | ||||||||||||
766 | if (!isl_int_is_zero(bmap->div[k][0])(isl_sioimath_sgn(*(bmap->div[k][0])) == 0)) | ||||||||||||
767 | break; | ||||||||||||
768 | if (k <= 0) | ||||||||||||
769 | return bmap; | ||||||||||||
770 | |||||||||||||
771 | size = round_up(4 * bmap->n_div / 3 - 1); | ||||||||||||
772 | if (size == 0) | ||||||||||||
773 | return bmap; | ||||||||||||
774 | elim_for = isl_calloc_array(ctx, int, bmap->n_div)((int *)isl_calloc_or_die(ctx, bmap->n_div, sizeof(int))); | ||||||||||||
775 | bits = ffs(size) - 1; | ||||||||||||
776 | index = isl_calloc_array(ctx, int, size)((int *)isl_calloc_or_die(ctx, size, sizeof(int))); | ||||||||||||
777 | if (!elim_for || !index) | ||||||||||||
778 | goto out; | ||||||||||||
779 | eq = isl_blk_alloc(ctx, 1+total); | ||||||||||||
780 | if (isl_blk_is_error(eq)) | ||||||||||||
781 | goto out; | ||||||||||||
782 | |||||||||||||
783 | isl_seq_clr(eq.data, 1+total); | ||||||||||||
784 | index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1; | ||||||||||||
785 | for (--k; k >= 0; --k) { | ||||||||||||
786 | uint32_t hash; | ||||||||||||
787 | |||||||||||||
788 | if (isl_int_is_zero(bmap->div[k][0])(isl_sioimath_sgn(*(bmap->div[k][0])) == 0)) | ||||||||||||
789 | continue; | ||||||||||||
790 | |||||||||||||
791 | hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits); | ||||||||||||
792 | for (h = hash; index[h]; h = (h+1) % size) | ||||||||||||
793 | if (isl_seq_eq(bmap->div[k], | ||||||||||||
794 | bmap->div[index[h]-1], 2+total)) | ||||||||||||
795 | break; | ||||||||||||
796 | if (index[h]) { | ||||||||||||
797 | *progress = 1; | ||||||||||||
798 | l = index[h] - 1; | ||||||||||||
799 | elim_for[l] = k + 1; | ||||||||||||
800 | } | ||||||||||||
801 | index[h] = k+1; | ||||||||||||
802 | } | ||||||||||||
803 | for (l = bmap->n_div - 1; l >= 0; --l) { | ||||||||||||
804 | if (!elim_for[l]) | ||||||||||||
805 | continue; | ||||||||||||
806 | k = elim_for[l] - 1; | ||||||||||||
807 | isl_int_set_si(eq.data[1+total_var+k], -1)isl_sioimath_set_si((eq.data[1+total_var+k]), -1); | ||||||||||||
808 | isl_int_set_si(eq.data[1+total_var+l], 1)isl_sioimath_set_si((eq.data[1+total_var+l]), 1); | ||||||||||||
809 | bmap = eliminate_div(bmap, eq.data, l, 1); | ||||||||||||
810 | if (!bmap) | ||||||||||||
811 | break; | ||||||||||||
812 | isl_int_set_si(eq.data[1+total_var+k], 0)isl_sioimath_set_si((eq.data[1+total_var+k]), 0); | ||||||||||||
813 | isl_int_set_si(eq.data[1+total_var+l], 0)isl_sioimath_set_si((eq.data[1+total_var+l]), 0); | ||||||||||||
814 | } | ||||||||||||
815 | |||||||||||||
816 | isl_blk_free(ctx, eq); | ||||||||||||
817 | out: | ||||||||||||
818 | free(index); | ||||||||||||
819 | free(elim_for); | ||||||||||||
820 | return bmap; | ||||||||||||
821 | } | ||||||||||||
822 | |||||||||||||
823 | static int n_pure_div_eq(struct isl_basic_map *bmap) | ||||||||||||
824 | { | ||||||||||||
825 | int i, j; | ||||||||||||
826 | unsigned total; | ||||||||||||
827 | |||||||||||||
828 | total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
829 | for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) { | ||||||||||||
830 | while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j])(isl_sioimath_sgn(*(bmap->eq[i][1 + total + j])) == 0)) | ||||||||||||
831 | --j; | ||||||||||||
832 | if (j < 0) | ||||||||||||
833 | break; | ||||||||||||
834 | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1) | ||||||||||||
835 | return 0; | ||||||||||||
836 | } | ||||||||||||
837 | return i; | ||||||||||||
838 | } | ||||||||||||
839 | |||||||||||||
840 | /* Normalize divs that appear in equalities. | ||||||||||||
841 | * | ||||||||||||
842 | * In particular, we assume that bmap contains some equalities | ||||||||||||
843 | * of the form | ||||||||||||
844 | * | ||||||||||||
845 | * a x = m * e_i | ||||||||||||
846 | * | ||||||||||||
847 | * and we want to replace the set of e_i by a minimal set and | ||||||||||||
848 | * such that the new e_i have a canonical representation in terms | ||||||||||||
849 | * of the vector x. | ||||||||||||
850 | * If any of the equalities involves more than one divs, then | ||||||||||||
851 | * we currently simply bail out. | ||||||||||||
852 | * | ||||||||||||
853 | * Let us first additionally assume that all equalities involve | ||||||||||||
854 | * a div. The equalities then express modulo constraints on the | ||||||||||||
855 | * remaining variables and we can use "parameter compression" | ||||||||||||
856 | * to find a minimal set of constraints. The result is a transformation | ||||||||||||
857 | * | ||||||||||||
858 | * x = T(x') = x_0 + G x' | ||||||||||||
859 | * | ||||||||||||
860 | * with G a lower-triangular matrix with all elements below the diagonal | ||||||||||||
861 | * non-negative and smaller than the diagonal element on the same row. | ||||||||||||
862 | * We first normalize x_0 by making the same property hold in the affine | ||||||||||||
863 | * T matrix. | ||||||||||||
864 | * The rows i of G with a 1 on the diagonal do not impose any modulo | ||||||||||||
865 | * constraint and simply express x_i = x'_i. | ||||||||||||
866 | * For each of the remaining rows i, we introduce a div and a corresponding | ||||||||||||
867 | * equality. In particular | ||||||||||||
868 | * | ||||||||||||
869 | * g_ii e_j = x_i - g_i(x') | ||||||||||||
870 | * | ||||||||||||
871 | * where each x'_k is replaced either by x_k (if g_kk = 1) or the | ||||||||||||
872 | * corresponding div (if g_kk != 1). | ||||||||||||
873 | * | ||||||||||||
874 | * If there are any equalities not involving any div, then we | ||||||||||||
875 | * first apply a variable compression on the variables x: | ||||||||||||
876 | * | ||||||||||||
877 | * x = C x'' x'' = C_2 x | ||||||||||||
878 | * | ||||||||||||
879 | * and perform the above parameter compression on A C instead of on A. | ||||||||||||
880 | * The resulting compression is then of the form | ||||||||||||
881 | * | ||||||||||||
882 | * x'' = T(x') = x_0 + G x' | ||||||||||||
883 | * | ||||||||||||
884 | * and in constructing the new divs and the corresponding equalities, | ||||||||||||
885 | * we have to replace each x'', i.e., the x'_k with (g_kk = 1), | ||||||||||||
886 | * by the corresponding row from C_2. | ||||||||||||
887 | */ | ||||||||||||
888 | static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap, | ||||||||||||
889 | int *progress) | ||||||||||||
890 | { | ||||||||||||
891 | int i, j, k; | ||||||||||||
892 | int total; | ||||||||||||
893 | int div_eq; | ||||||||||||
894 | struct isl_mat *B; | ||||||||||||
895 | struct isl_vec *d; | ||||||||||||
896 | struct isl_mat *T = NULL((void*)0); | ||||||||||||
897 | struct isl_mat *C = NULL((void*)0); | ||||||||||||
898 | struct isl_mat *C2 = NULL((void*)0); | ||||||||||||
899 | isl_int v; | ||||||||||||
900 | int *pos = NULL((void*)0); | ||||||||||||
901 | int dropped, needed; | ||||||||||||
902 | |||||||||||||
903 | if (!bmap) | ||||||||||||
904 | return NULL((void*)0); | ||||||||||||
905 | |||||||||||||
906 | if (bmap->n_div == 0) | ||||||||||||
907 | return bmap; | ||||||||||||
908 | |||||||||||||
909 | if (bmap->n_eq == 0) | ||||||||||||
910 | return bmap; | ||||||||||||
911 | |||||||||||||
912 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS)(!!(((bmap)->flags) & ((1 << 6))))) | ||||||||||||
913 | return bmap; | ||||||||||||
914 | |||||||||||||
915 | total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
916 | div_eq = n_pure_div_eq(bmap); | ||||||||||||
917 | if (div_eq == 0) | ||||||||||||
918 | return bmap; | ||||||||||||
919 | |||||||||||||
920 | if (div_eq < bmap->n_eq) { | ||||||||||||
921 | B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq, | ||||||||||||
922 | bmap->n_eq - div_eq, 0, 1 + total); | ||||||||||||
923 | C = isl_mat_variable_compression(B, &C2); | ||||||||||||
924 | if (!C || !C2) | ||||||||||||
925 | goto error; | ||||||||||||
926 | if (C->n_col == 0) { | ||||||||||||
927 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
928 | isl_mat_free(C); | ||||||||||||
929 | isl_mat_free(C2); | ||||||||||||
930 | goto done; | ||||||||||||
931 | } | ||||||||||||
932 | } | ||||||||||||
933 | |||||||||||||
934 | d = isl_vec_alloc(bmap->ctx, div_eq); | ||||||||||||
935 | if (!d) | ||||||||||||
936 | goto error; | ||||||||||||
937 | for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) { | ||||||||||||
938 | while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j])(isl_sioimath_sgn(*(bmap->eq[i][1 + total + j])) == 0)) | ||||||||||||
939 | --j; | ||||||||||||
940 | isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j])isl_sioimath_set((d->block.data[i]), *(bmap->eq[i][1 + total + j])); | ||||||||||||
941 | } | ||||||||||||
942 | B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total); | ||||||||||||
943 | |||||||||||||
944 | if (C) { | ||||||||||||
945 | B = isl_mat_product(B, C); | ||||||||||||
946 | C = NULL((void*)0); | ||||||||||||
947 | } | ||||||||||||
948 | |||||||||||||
949 | T = isl_mat_parameter_compression(B, d); | ||||||||||||
950 | if (!T) | ||||||||||||
951 | goto error; | ||||||||||||
952 | if (T->n_col == 0) { | ||||||||||||
953 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
954 | isl_mat_free(C2); | ||||||||||||
955 | isl_mat_free(T); | ||||||||||||
956 | goto done; | ||||||||||||
957 | } | ||||||||||||
958 | isl_int_init(v)isl_sioimath_init((v)); | ||||||||||||
959 | for (i = 0; i < T->n_row - 1; ++i) { | ||||||||||||
960 | isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i])isl_sioimath_fdiv_q((v), *(T->row[1 + i][0]), *(T->row[ 1 + i][1 + i])); | ||||||||||||
961 | if (isl_int_is_zero(v)(isl_sioimath_sgn(*(v)) == 0)) | ||||||||||||
962 | continue; | ||||||||||||
963 | isl_mat_col_submul(T, 0, v, 1 + i); | ||||||||||||
964 | } | ||||||||||||
965 | isl_int_clear(v)isl_sioimath_clear((v)); | ||||||||||||
966 | pos = isl_alloc_array(bmap->ctx, int, T->n_row)((int *)isl_malloc_or_die(bmap->ctx, (T->n_row)*sizeof( int))); | ||||||||||||
967 | if (!pos) | ||||||||||||
968 | goto error; | ||||||||||||
969 | /* We have to be careful because dropping equalities may reorder them */ | ||||||||||||
970 | dropped = 0; | ||||||||||||
971 | for (j = bmap->n_div - 1; j >= 0; --j) { | ||||||||||||
972 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
973 | if (!isl_int_is_zero(bmap->eq[i][1 + total + j])(isl_sioimath_sgn(*(bmap->eq[i][1 + total + j])) == 0)) | ||||||||||||
974 | break; | ||||||||||||
975 | if (i < bmap->n_eq) { | ||||||||||||
976 | bmap = isl_basic_map_drop_div(bmap, j); | ||||||||||||
977 | isl_basic_map_drop_equality(bmap, i); | ||||||||||||
978 | ++dropped; | ||||||||||||
979 | } | ||||||||||||
980 | } | ||||||||||||
981 | pos[0] = 0; | ||||||||||||
982 | needed = 0; | ||||||||||||
983 | for (i = 1; i < T->n_row; ++i) { | ||||||||||||
984 | if (isl_int_is_one(T->row[i][i])(isl_sioimath_cmp_si(*(T->row[i][i]), 1) == 0)) | ||||||||||||
985 | pos[i] = i; | ||||||||||||
986 | else | ||||||||||||
987 | needed++; | ||||||||||||
988 | } | ||||||||||||
989 | if (needed > dropped) { | ||||||||||||
990 | bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), | ||||||||||||
991 | needed, needed, 0); | ||||||||||||
992 | if (!bmap) | ||||||||||||
993 | goto error; | ||||||||||||
994 | } | ||||||||||||
995 | for (i = 1; i < T->n_row; ++i) { | ||||||||||||
996 | if (isl_int_is_one(T->row[i][i])(isl_sioimath_cmp_si(*(T->row[i][i]), 1) == 0)) | ||||||||||||
997 | continue; | ||||||||||||
998 | k = isl_basic_map_alloc_div(bmap); | ||||||||||||
999 | pos[i] = 1 + total + k; | ||||||||||||
1000 | isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div); | ||||||||||||
1001 | isl_int_set(bmap->div[k][0], T->row[i][i])isl_sioimath_set((bmap->div[k][0]), *(T->row[i][i])); | ||||||||||||
1002 | if (C2) | ||||||||||||
1003 | isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total); | ||||||||||||
1004 | else | ||||||||||||
1005 | isl_int_set_si(bmap->div[k][1 + i], 1)isl_sioimath_set_si((bmap->div[k][1 + i]), 1); | ||||||||||||
1006 | for (j = 0; j < i; ++j) { | ||||||||||||
1007 | if (isl_int_is_zero(T->row[i][j])(isl_sioimath_sgn(*(T->row[i][j])) == 0)) | ||||||||||||
1008 | continue; | ||||||||||||
1009 | if (pos[j] < T->n_row && C2) | ||||||||||||
1010 | isl_seq_submul(bmap->div[k] + 1, T->row[i][j], | ||||||||||||
1011 | C2->row[pos[j]], 1 + total); | ||||||||||||
1012 | else | ||||||||||||
1013 | isl_int_neg(bmap->div[k][1 + pos[j]],isl_sioimath_neg((bmap->div[k][1 + pos[j]]), *(T->row[i ][j])) | ||||||||||||
1014 | T->row[i][j])isl_sioimath_neg((bmap->div[k][1 + pos[j]]), *(T->row[i ][j])); | ||||||||||||
1015 | } | ||||||||||||
1016 | j = isl_basic_map_alloc_equality(bmap); | ||||||||||||
1017 | isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div); | ||||||||||||
1018 | isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0])isl_sioimath_set((bmap->eq[j][pos[i]]), *(bmap->div[k][ 0])); | ||||||||||||
1019 | } | ||||||||||||
1020 | free(pos); | ||||||||||||
1021 | isl_mat_free(C2); | ||||||||||||
1022 | isl_mat_free(T); | ||||||||||||
1023 | |||||||||||||
1024 | if (progress) | ||||||||||||
1025 | *progress = 1; | ||||||||||||
1026 | done: | ||||||||||||
1027 | ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS)(((bmap)->flags) |= ((1 << 6))); | ||||||||||||
1028 | |||||||||||||
1029 | return bmap; | ||||||||||||
1030 | error: | ||||||||||||
1031 | free(pos); | ||||||||||||
1032 | isl_mat_free(C); | ||||||||||||
1033 | isl_mat_free(C2); | ||||||||||||
1034 | isl_mat_free(T); | ||||||||||||
1035 | return bmap; | ||||||||||||
1036 | } | ||||||||||||
1037 | |||||||||||||
1038 | static __isl_give isl_basic_map *set_div_from_lower_bound( | ||||||||||||
1039 | __isl_take isl_basic_map *bmap, int div, int ineq) | ||||||||||||
1040 | { | ||||||||||||
1041 | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1042 | |||||||||||||
1043 | isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div); | ||||||||||||
1044 | isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div])isl_sioimath_set((bmap->div[div][0]), *(bmap->ineq[ineq ][total + div])); | ||||||||||||
1045 | isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0])isl_sioimath_add((bmap->div[div][1]), *(bmap->div[div][ 1]), *(bmap->div[div][0])); | ||||||||||||
1046 | isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1)isl_sioimath_sub_ui((bmap->div[div][1]), *(bmap->div[div ][1]), 1); | ||||||||||||
1047 | isl_int_set_si(bmap->div[div][1 + total + div], 0)isl_sioimath_set_si((bmap->div[div][1 + total + div]), 0); | ||||||||||||
1048 | |||||||||||||
1049 | return bmap; | ||||||||||||
1050 | } | ||||||||||||
1051 | |||||||||||||
1052 | /* Check whether it is ok to define a div based on an inequality. | ||||||||||||
1053 | * To avoid the introduction of circular definitions of divs, we | ||||||||||||
1054 | * do not allow such a definition if the resulting expression would refer to | ||||||||||||
1055 | * any other undefined divs or if any known div is defined in | ||||||||||||
1056 | * terms of the unknown div. | ||||||||||||
1057 | */ | ||||||||||||
1058 | static isl_bool ok_to_set_div_from_bound(__isl_keep isl_basic_map *bmap, | ||||||||||||
1059 | int div, int ineq) | ||||||||||||
1060 | { | ||||||||||||
1061 | int j; | ||||||||||||
1062 | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1063 | |||||||||||||
1064 | /* Not defined in terms of unknown divs */ | ||||||||||||
1065 | for (j = 0; j < bmap->n_div; ++j) { | ||||||||||||
1066 | if (div == j) | ||||||||||||
1067 | continue; | ||||||||||||
1068 | if (isl_int_is_zero(bmap->ineq[ineq][total + j])(isl_sioimath_sgn(*(bmap->ineq[ineq][total + j])) == 0)) | ||||||||||||
1069 | continue; | ||||||||||||
1070 | if (isl_int_is_zero(bmap->div[j][0])(isl_sioimath_sgn(*(bmap->div[j][0])) == 0)) | ||||||||||||
1071 | return isl_bool_false; | ||||||||||||
1072 | } | ||||||||||||
1073 | |||||||||||||
1074 | /* No other div defined in terms of this one => avoid loops */ | ||||||||||||
1075 | for (j = 0; j < bmap->n_div; ++j) { | ||||||||||||
1076 | if (div == j) | ||||||||||||
1077 | continue; | ||||||||||||
1078 | if (isl_int_is_zero(bmap->div[j][0])(isl_sioimath_sgn(*(bmap->div[j][0])) == 0)) | ||||||||||||
1079 | continue; | ||||||||||||
1080 | if (!isl_int_is_zero(bmap->div[j][1 + total + div])(isl_sioimath_sgn(*(bmap->div[j][1 + total + div])) == 0)) | ||||||||||||
1081 | return isl_bool_false; | ||||||||||||
1082 | } | ||||||||||||
1083 | |||||||||||||
1084 | return isl_bool_true; | ||||||||||||
1085 | } | ||||||||||||
1086 | |||||||||||||
1087 | /* Would an expression for div "div" based on inequality "ineq" of "bmap" | ||||||||||||
1088 | * be a better expression than the current one? | ||||||||||||
1089 | * | ||||||||||||
1090 | * If we do not have any expression yet, then any expression would be better. | ||||||||||||
1091 | * Otherwise we check if the last variable involved in the inequality | ||||||||||||
1092 | * (disregarding the div that it would define) is in an earlier position | ||||||||||||
1093 | * than the last variable involved in the current div expression. | ||||||||||||
1094 | */ | ||||||||||||
1095 | static isl_bool better_div_constraint(__isl_keep isl_basic_map *bmap, | ||||||||||||
1096 | int div, int ineq) | ||||||||||||
1097 | { | ||||||||||||
1098 | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1099 | int last_div; | ||||||||||||
1100 | int last_ineq; | ||||||||||||
1101 | |||||||||||||
1102 | if (isl_int_is_zero(bmap->div[div][0])(isl_sioimath_sgn(*(bmap->div[div][0])) == 0)) | ||||||||||||
1103 | return isl_bool_true; | ||||||||||||
1104 | |||||||||||||
1105 | if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1, | ||||||||||||
1106 | bmap->n_div - (div + 1)) >= 0) | ||||||||||||
1107 | return isl_bool_false; | ||||||||||||
1108 | |||||||||||||
1109 | last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div); | ||||||||||||
1110 | last_div = isl_seq_last_non_zero(bmap->div[div] + 1, | ||||||||||||
1111 | total + bmap->n_div); | ||||||||||||
1112 | |||||||||||||
1113 | return last_ineq < last_div; | ||||||||||||
1114 | } | ||||||||||||
1115 | |||||||||||||
1116 | /* Given two constraints "k" and "l" that are opposite to each other, | ||||||||||||
1117 | * except for the constant term, check if we can use them | ||||||||||||
1118 | * to obtain an expression for one of the hitherto unknown divs or | ||||||||||||
1119 | * a "better" expression for a div for which we already have an expression. | ||||||||||||
1120 | * "sum" is the sum of the constant terms of the constraints. | ||||||||||||
1121 | * If this sum is strictly smaller than the coefficient of one | ||||||||||||
1122 | * of the divs, then this pair can be used define the div. | ||||||||||||
1123 | * To avoid the introduction of circular definitions of divs, we | ||||||||||||
1124 | * do not use the pair if the resulting expression would refer to | ||||||||||||
1125 | * any other undefined divs or if any known div is defined in | ||||||||||||
1126 | * terms of the unknown div. | ||||||||||||
1127 | */ | ||||||||||||
1128 | static __isl_give isl_basic_map *check_for_div_constraints( | ||||||||||||
1129 | __isl_take isl_basic_map *bmap, int k, int l, isl_int sum, | ||||||||||||
1130 | int *progress) | ||||||||||||
1131 | { | ||||||||||||
1132 | int i; | ||||||||||||
1133 | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1134 | |||||||||||||
1135 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
1136 | isl_bool set_div; | ||||||||||||
1137 | |||||||||||||
1138 | if (isl_int_is_zero(bmap->ineq[k][total + i])(isl_sioimath_sgn(*(bmap->ineq[k][total + i])) == 0)) | ||||||||||||
1139 | continue; | ||||||||||||
1140 | if (isl_int_abs_ge(sum, bmap->ineq[k][total + i])(isl_sioimath_abs_cmp(*(sum), *(bmap->ineq[k][total + i])) >= 0)) | ||||||||||||
1141 | continue; | ||||||||||||
1142 | set_div = better_div_constraint(bmap, i, k); | ||||||||||||
1143 | if (set_div >= 0 && set_div) | ||||||||||||
1144 | set_div = ok_to_set_div_from_bound(bmap, i, k); | ||||||||||||
1145 | if (set_div < 0) | ||||||||||||
1146 | return isl_basic_map_free(bmap); | ||||||||||||
1147 | if (!set_div) | ||||||||||||
1148 | break; | ||||||||||||
1149 | if (isl_int_is_pos(bmap->ineq[k][total + i])(isl_sioimath_sgn(*(bmap->ineq[k][total + i])) > 0)) | ||||||||||||
1150 | bmap = set_div_from_lower_bound(bmap, i, k); | ||||||||||||
1151 | else | ||||||||||||
1152 | bmap = set_div_from_lower_bound(bmap, i, l); | ||||||||||||
1153 | if (progress) | ||||||||||||
1154 | *progress = 1; | ||||||||||||
1155 | break; | ||||||||||||
1156 | } | ||||||||||||
1157 | return bmap; | ||||||||||||
1158 | } | ||||||||||||
1159 | |||||||||||||
1160 | __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints( | ||||||||||||
1161 | __isl_take isl_basic_map *bmap, int *progress, int detect_divs) | ||||||||||||
1162 | { | ||||||||||||
1163 | struct isl_constraint_index ci; | ||||||||||||
1164 | int k, l, h; | ||||||||||||
1165 | unsigned total = isl_basic_map_total_dim(bmap); | ||||||||||||
1166 | isl_int sum; | ||||||||||||
1167 | |||||||||||||
1168 | if (!bmap
| ||||||||||||
1169 | return bmap; | ||||||||||||
1170 | |||||||||||||
1171 | if (create_constraint_index(&ci, bmap) < 0) | ||||||||||||
1172 | return bmap; | ||||||||||||
1173 | |||||||||||||
1174 | h = isl_seq_get_hash_bits(bmap->ineq[0] + 1, total, ci.bits); | ||||||||||||
1175 | ci.index[h] = &bmap->ineq[0]; | ||||||||||||
1176 | for (k = 1; k < bmap->n_ineq; ++k) { | ||||||||||||
1177 | h = hash_index(&ci, bmap, k); | ||||||||||||
1178 | if (!ci.index[h]) { | ||||||||||||
1179 | ci.index[h] = &bmap->ineq[k]; | ||||||||||||
1180 | continue; | ||||||||||||
1181 | } | ||||||||||||
1182 | if (progress) | ||||||||||||
1183 | *progress = 1; | ||||||||||||
1184 | l = ci.index[h] - &bmap->ineq[0]; | ||||||||||||
1185 | if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0])(isl_sioimath_cmp(*(bmap->ineq[k][0]), *(bmap->ineq[l][ 0])) < 0)) | ||||||||||||
1186 | swap_inequality(bmap, k, l); | ||||||||||||
1187 | isl_basic_map_drop_inequality(bmap, k); | ||||||||||||
1188 | --k; | ||||||||||||
1189 | } | ||||||||||||
1190 | isl_int_init(sum)isl_sioimath_init((sum)); | ||||||||||||
1191 | for (k = 0; k < bmap->n_ineq-1; ++k) { | ||||||||||||
1192 | isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total); | ||||||||||||
1193 | h = hash_index(&ci, bmap, k); | ||||||||||||
1194 | isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total); | ||||||||||||
1195 | if (!ci.index[h]) | ||||||||||||
1196 | continue; | ||||||||||||
1197 | l = ci.index[h] - &bmap->ineq[0]; | ||||||||||||
1198 | isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0])isl_sioimath_add((sum), *(bmap->ineq[k][0]), *(bmap->ineq [l][0])); | ||||||||||||
1199 | if (isl_int_is_pos(sum)(isl_sioimath_sgn(*(sum)) > 0)) { | ||||||||||||
1200 | if (detect_divs) | ||||||||||||
1201 | bmap = check_for_div_constraints(bmap, k, l, | ||||||||||||
1202 | sum, progress); | ||||||||||||
1203 | continue; | ||||||||||||
1204 | } | ||||||||||||
1205 | if (isl_int_is_zero(sum)(isl_sioimath_sgn(*(sum)) == 0)) { | ||||||||||||
1206 | /* We need to break out of the loop after these | ||||||||||||
1207 | * changes since the contents of the hash | ||||||||||||
1208 | * will no longer be valid. | ||||||||||||
1209 | * Plus, we probably we want to regauss first. | ||||||||||||
1210 | */ | ||||||||||||
1211 | if (progress
| ||||||||||||
1212 | *progress = 1; | ||||||||||||
1213 | isl_basic_map_drop_inequality(bmap, l); | ||||||||||||
1214 | isl_basic_map_inequality_to_equality(bmap, k); | ||||||||||||
1215 | } else | ||||||||||||
1216 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
1217 | break; | ||||||||||||
1218 | } | ||||||||||||
1219 | isl_int_clear(sum)isl_sioimath_clear((sum)); | ||||||||||||
1220 | |||||||||||||
1221 | constraint_index_free(&ci); | ||||||||||||
1222 | return bmap; | ||||||||||||
1223 | } | ||||||||||||
1224 | |||||||||||||
1225 | /* Detect all pairs of inequalities that form an equality. | ||||||||||||
1226 | * | ||||||||||||
1227 | * isl_basic_map_remove_duplicate_constraints detects at most one such pair. | ||||||||||||
1228 | * Call it repeatedly while it is making progress. | ||||||||||||
1229 | */ | ||||||||||||
1230 | __isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs( | ||||||||||||
1231 | __isl_take isl_basic_map *bmap, int *progress) | ||||||||||||
1232 | { | ||||||||||||
1233 | int duplicate; | ||||||||||||
1234 | |||||||||||||
1235 | do { | ||||||||||||
1236 | duplicate = 0; | ||||||||||||
1237 | bmap = isl_basic_map_remove_duplicate_constraints(bmap, | ||||||||||||
1238 | &duplicate, 0); | ||||||||||||
1239 | if (progress
| ||||||||||||
1240 | *progress = 1; | ||||||||||||
1241 | } while (duplicate); | ||||||||||||
1242 | |||||||||||||
1243 | return bmap; | ||||||||||||
1244 | } | ||||||||||||
1245 | |||||||||||||
1246 | /* Eliminate knowns divs from constraints where they appear with | ||||||||||||
1247 | * a (positive or negative) unit coefficient. | ||||||||||||
1248 | * | ||||||||||||
1249 | * That is, replace | ||||||||||||
1250 | * | ||||||||||||
1251 | * floor(e/m) + f >= 0 | ||||||||||||
1252 | * | ||||||||||||
1253 | * by | ||||||||||||
1254 | * | ||||||||||||
1255 | * e + m f >= 0 | ||||||||||||
1256 | * | ||||||||||||
1257 | * and | ||||||||||||
1258 | * | ||||||||||||
1259 | * -floor(e/m) + f >= 0 | ||||||||||||
1260 | * | ||||||||||||
1261 | * by | ||||||||||||
1262 | * | ||||||||||||
1263 | * -e + m f + m - 1 >= 0 | ||||||||||||
1264 | * | ||||||||||||
1265 | * The first conversion is valid because floor(e/m) >= -f is equivalent | ||||||||||||
1266 | * to e/m >= -f because -f is an integral expression. | ||||||||||||
1267 | * The second conversion follows from the fact that | ||||||||||||
1268 | * | ||||||||||||
1269 | * -floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m) | ||||||||||||
1270 | * | ||||||||||||
1271 | * | ||||||||||||
1272 | * Note that one of the div constraints may have been eliminated | ||||||||||||
1273 | * due to being redundant with respect to the constraint that is | ||||||||||||
1274 | * being modified by this function. The modified constraint may | ||||||||||||
1275 | * no longer imply this div constraint, so we add it back to make | ||||||||||||
1276 | * sure we do not lose any information. | ||||||||||||
1277 | * | ||||||||||||
1278 | * We skip integral divs, i.e., those with denominator 1, as we would | ||||||||||||
1279 | * risk eliminating the div from the div constraints. We do not need | ||||||||||||
1280 | * to handle those divs here anyway since the div constraints will turn | ||||||||||||
1281 | * out to form an equality and this equality can then be used to eliminate | ||||||||||||
1282 | * the div from all constraints. | ||||||||||||
1283 | */ | ||||||||||||
1284 | static __isl_give isl_basic_map *eliminate_unit_divs( | ||||||||||||
1285 | __isl_take isl_basic_map *bmap, int *progress) | ||||||||||||
1286 | { | ||||||||||||
1287 | int i, j; | ||||||||||||
1288 | isl_ctx *ctx; | ||||||||||||
1289 | unsigned total; | ||||||||||||
1290 | |||||||||||||
1291 | if (!bmap) | ||||||||||||
1292 | return NULL((void*)0); | ||||||||||||
1293 | |||||||||||||
1294 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
1295 | total = 1 + isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1296 | |||||||||||||
1297 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
1298 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
1299 | continue; | ||||||||||||
1300 | if (isl_int_is_one(bmap->div[i][0])(isl_sioimath_cmp_si(*(bmap->div[i][0]), 1) == 0)) | ||||||||||||
1301 | continue; | ||||||||||||
1302 | for (j = 0; j < bmap->n_ineq; ++j) { | ||||||||||||
1303 | int s; | ||||||||||||
1304 | |||||||||||||
1305 | if (!isl_int_is_one(bmap->ineq[j][total + i])(isl_sioimath_cmp_si(*(bmap->ineq[j][total + i]), 1) == 0) && | ||||||||||||
1306 | !isl_int_is_negone(bmap->ineq[j][total + i])(isl_sioimath_cmp_si(*(bmap->ineq[j][total + i]), -1) == 0 )) | ||||||||||||
1307 | continue; | ||||||||||||
1308 | |||||||||||||
1309 | *progress = 1; | ||||||||||||
1310 | |||||||||||||
1311 | s = isl_int_sgn(bmap->ineq[j][total + i])isl_sioimath_sgn(*(bmap->ineq[j][total + i])); | ||||||||||||
1312 | isl_int_set_si(bmap->ineq[j][total + i], 0)isl_sioimath_set_si((bmap->ineq[j][total + i]), 0); | ||||||||||||
1313 | if (s < 0) | ||||||||||||
1314 | isl_seq_combine(bmap->ineq[j], | ||||||||||||
1315 | ctx->negone, bmap->div[i] + 1, | ||||||||||||
1316 | bmap->div[i][0], bmap->ineq[j], | ||||||||||||
1317 | total + bmap->n_div); | ||||||||||||
1318 | else | ||||||||||||
1319 | isl_seq_combine(bmap->ineq[j], | ||||||||||||
1320 | ctx->one, bmap->div[i] + 1, | ||||||||||||
1321 | bmap->div[i][0], bmap->ineq[j], | ||||||||||||
1322 | total + bmap->n_div); | ||||||||||||
1323 | if (s < 0) { | ||||||||||||
1324 | isl_int_add(bmap->ineq[j][0],isl_sioimath_add((bmap->ineq[j][0]), *(bmap->ineq[j][0] ), *(bmap->div[i][0])) | ||||||||||||
1325 | bmap->ineq[j][0], bmap->div[i][0])isl_sioimath_add((bmap->ineq[j][0]), *(bmap->ineq[j][0] ), *(bmap->div[i][0])); | ||||||||||||
1326 | isl_int_sub_ui(bmap->ineq[j][0],isl_sioimath_sub_ui((bmap->ineq[j][0]), *(bmap->ineq[j] [0]), 1) | ||||||||||||
1327 | bmap->ineq[j][0], 1)isl_sioimath_sub_ui((bmap->ineq[j][0]), *(bmap->ineq[j] [0]), 1); | ||||||||||||
1328 | } | ||||||||||||
1329 | |||||||||||||
1330 | bmap = isl_basic_map_extend_constraints(bmap, 0, 1); | ||||||||||||
1331 | if (isl_basic_map_add_div_constraint(bmap, i, s) < 0) | ||||||||||||
1332 | return isl_basic_map_free(bmap); | ||||||||||||
1333 | } | ||||||||||||
1334 | } | ||||||||||||
1335 | |||||||||||||
1336 | return bmap; | ||||||||||||
1337 | } | ||||||||||||
1338 | |||||||||||||
1339 | __isl_give isl_basic_map *isl_basic_map_simplify(__isl_take isl_basic_map *bmap) | ||||||||||||
1340 | { | ||||||||||||
1341 | int progress = 1; | ||||||||||||
1342 | if (!bmap) | ||||||||||||
1343 | return NULL((void*)0); | ||||||||||||
1344 | while (progress) { | ||||||||||||
1345 | isl_bool empty; | ||||||||||||
1346 | |||||||||||||
1347 | progress = 0; | ||||||||||||
1348 | empty = isl_basic_map_plain_is_empty(bmap); | ||||||||||||
1349 | if (empty < 0) | ||||||||||||
1350 | return isl_basic_map_free(bmap); | ||||||||||||
1351 | if (empty) | ||||||||||||
1352 | break; | ||||||||||||
1353 | bmap = isl_basic_map_normalize_constraints(bmap); | ||||||||||||
1354 | bmap = reduce_div_coefficients(bmap); | ||||||||||||
1355 | bmap = normalize_div_expressions(bmap); | ||||||||||||
1356 | bmap = remove_duplicate_divs(bmap, &progress); | ||||||||||||
1357 | bmap = eliminate_unit_divs(bmap, &progress); | ||||||||||||
1358 | bmap = eliminate_divs_eq(bmap, &progress); | ||||||||||||
1359 | bmap = eliminate_divs_ineq(bmap, &progress); | ||||||||||||
1360 | bmap = isl_basic_map_gauss(bmap, &progress); | ||||||||||||
1361 | /* requires equalities in normal form */ | ||||||||||||
1362 | bmap = normalize_divs(bmap, &progress); | ||||||||||||
1363 | bmap = isl_basic_map_remove_duplicate_constraints(bmap, | ||||||||||||
1364 | &progress, 1); | ||||||||||||
1365 | if (bmap && progress) | ||||||||||||
1366 | ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS)(((bmap)->flags) &= ~((1 << 8))); | ||||||||||||
1367 | } | ||||||||||||
1368 | return bmap; | ||||||||||||
1369 | } | ||||||||||||
1370 | |||||||||||||
1371 | struct isl_basic_setisl_basic_map *isl_basic_set_simplify(struct isl_basic_setisl_basic_map *bset) | ||||||||||||
1372 | { | ||||||||||||
1373 | return bset_from_bmap(isl_basic_map_simplify(bset_to_bmap(bset))); | ||||||||||||
1374 | } | ||||||||||||
1375 | |||||||||||||
1376 | |||||||||||||
1377 | isl_bool isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap, | ||||||||||||
1378 | isl_int *constraint, unsigned div) | ||||||||||||
1379 | { | ||||||||||||
1380 | unsigned pos; | ||||||||||||
1381 | |||||||||||||
1382 | if (!bmap) | ||||||||||||
1383 | return isl_bool_error; | ||||||||||||
1384 | |||||||||||||
1385 | pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div; | ||||||||||||
1386 | |||||||||||||
1387 | if (isl_int_eq(constraint[pos], bmap->div[div][0])(isl_sioimath_cmp(*(constraint[pos]), *(bmap->div[div][0]) ) == 0)) { | ||||||||||||
1388 | int neg; | ||||||||||||
1389 | isl_int_sub(bmap->div[div][1],isl_sioimath_sub((bmap->div[div][1]), *(bmap->div[div][ 1]), *(bmap->div[div][0])) | ||||||||||||
1390 | bmap->div[div][1], bmap->div[div][0])isl_sioimath_sub((bmap->div[div][1]), *(bmap->div[div][ 1]), *(bmap->div[div][0])); | ||||||||||||
1391 | isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1)isl_sioimath_add_ui((bmap->div[div][1]), *(bmap->div[div ][1]), 1); | ||||||||||||
1392 | neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos); | ||||||||||||
1393 | isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1)isl_sioimath_sub_ui((bmap->div[div][1]), *(bmap->div[div ][1]), 1); | ||||||||||||
1394 | isl_int_add(bmap->div[div][1],isl_sioimath_add((bmap->div[div][1]), *(bmap->div[div][ 1]), *(bmap->div[div][0])) | ||||||||||||
1395 | bmap->div[div][1], bmap->div[div][0])isl_sioimath_add((bmap->div[div][1]), *(bmap->div[div][ 1]), *(bmap->div[div][0])); | ||||||||||||
1396 | if (!neg) | ||||||||||||
1397 | return isl_bool_false; | ||||||||||||
1398 | if (isl_seq_first_non_zero(constraint+pos+1, | ||||||||||||
1399 | bmap->n_div-div-1) != -1) | ||||||||||||
1400 | return isl_bool_false; | ||||||||||||
1401 | } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])(isl_sioimath_abs_cmp(*(constraint[pos]), *(bmap->div[div] [0])) == 0)) { | ||||||||||||
1402 | if (!isl_seq_eq(constraint, bmap->div[div]+1, pos)) | ||||||||||||
1403 | return isl_bool_false; | ||||||||||||
1404 | if (isl_seq_first_non_zero(constraint+pos+1, | ||||||||||||
1405 | bmap->n_div-div-1) != -1) | ||||||||||||
1406 | return isl_bool_false; | ||||||||||||
1407 | } else | ||||||||||||
1408 | return isl_bool_false; | ||||||||||||
1409 | |||||||||||||
1410 | return isl_bool_true; | ||||||||||||
1411 | } | ||||||||||||
1412 | |||||||||||||
1413 | isl_bool isl_basic_set_is_div_constraint(__isl_keep isl_basic_setisl_basic_map *bset, | ||||||||||||
1414 | isl_int *constraint, unsigned div) | ||||||||||||
1415 | { | ||||||||||||
1416 | return isl_basic_map_is_div_constraint(bset, constraint, div); | ||||||||||||
1417 | } | ||||||||||||
1418 | |||||||||||||
1419 | |||||||||||||
1420 | /* If the only constraints a div d=floor(f/m) | ||||||||||||
1421 | * appears in are its two defining constraints | ||||||||||||
1422 | * | ||||||||||||
1423 | * f - m d >=0 | ||||||||||||
1424 | * -(f - (m - 1)) + m d >= 0 | ||||||||||||
1425 | * | ||||||||||||
1426 | * then it can safely be removed. | ||||||||||||
1427 | */ | ||||||||||||
1428 | static isl_bool div_is_redundant(__isl_keep isl_basic_map *bmap, int div) | ||||||||||||
1429 | { | ||||||||||||
1430 | int i; | ||||||||||||
1431 | unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div; | ||||||||||||
1432 | |||||||||||||
1433 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
1434 | if (!isl_int_is_zero(bmap->eq[i][pos])(isl_sioimath_sgn(*(bmap->eq[i][pos])) == 0)) | ||||||||||||
1435 | return isl_bool_false; | ||||||||||||
1436 | |||||||||||||
1437 | for (i = 0; i < bmap->n_ineq; ++i) { | ||||||||||||
1438 | isl_bool red; | ||||||||||||
1439 | |||||||||||||
1440 | if (isl_int_is_zero(bmap->ineq[i][pos])(isl_sioimath_sgn(*(bmap->ineq[i][pos])) == 0)) | ||||||||||||
1441 | continue; | ||||||||||||
1442 | red = isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div); | ||||||||||||
1443 | if (red < 0 || !red) | ||||||||||||
1444 | return red; | ||||||||||||
1445 | } | ||||||||||||
1446 | |||||||||||||
1447 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
1448 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
1449 | continue; | ||||||||||||
1450 | if (!isl_int_is_zero(bmap->div[i][1+pos])(isl_sioimath_sgn(*(bmap->div[i][1+pos])) == 0)) | ||||||||||||
1451 | return isl_bool_false; | ||||||||||||
1452 | } | ||||||||||||
1453 | |||||||||||||
1454 | return isl_bool_true; | ||||||||||||
1455 | } | ||||||||||||
1456 | |||||||||||||
1457 | /* | ||||||||||||
1458 | * Remove divs that don't occur in any of the constraints or other divs. | ||||||||||||
1459 | * These can arise when dropping constraints from a basic map or | ||||||||||||
1460 | * when the divs of a basic map have been temporarily aligned | ||||||||||||
1461 | * with the divs of another basic map. | ||||||||||||
1462 | */ | ||||||||||||
1463 | static __isl_give isl_basic_map *remove_redundant_divs( | ||||||||||||
1464 | __isl_take isl_basic_map *bmap) | ||||||||||||
1465 | { | ||||||||||||
1466 | int i; | ||||||||||||
1467 | |||||||||||||
1468 | if (!bmap) | ||||||||||||
1469 | return NULL((void*)0); | ||||||||||||
1470 | |||||||||||||
1471 | for (i = bmap->n_div-1; i >= 0; --i) { | ||||||||||||
1472 | isl_bool redundant; | ||||||||||||
1473 | |||||||||||||
1474 | redundant = div_is_redundant(bmap, i); | ||||||||||||
1475 | if (redundant < 0) | ||||||||||||
1476 | return isl_basic_map_free(bmap); | ||||||||||||
1477 | if (!redundant) | ||||||||||||
1478 | continue; | ||||||||||||
1479 | bmap = isl_basic_map_drop_div(bmap, i); | ||||||||||||
1480 | } | ||||||||||||
1481 | return bmap; | ||||||||||||
1482 | } | ||||||||||||
1483 | |||||||||||||
1484 | /* Mark "bmap" as final, without checking for obviously redundant | ||||||||||||
1485 | * integer divisions. This function should be used when "bmap" | ||||||||||||
1486 | * is known not to involve any such integer divisions. | ||||||||||||
1487 | */ | ||||||||||||
1488 | __isl_give isl_basic_map *isl_basic_map_mark_final( | ||||||||||||
1489 | __isl_take isl_basic_map *bmap) | ||||||||||||
1490 | { | ||||||||||||
1491 | if (!bmap) | ||||||||||||
1492 | return NULL((void*)0); | ||||||||||||
1493 | ISL_F_SET(bmap, ISL_BASIC_SET_FINAL)(((bmap)->flags) |= ((1 << 0))); | ||||||||||||
1494 | return bmap; | ||||||||||||
1495 | } | ||||||||||||
1496 | |||||||||||||
1497 | /* Mark "bmap" as final, after removing obviously redundant integer divisions. | ||||||||||||
1498 | */ | ||||||||||||
1499 | __isl_give isl_basic_map *isl_basic_map_finalize(__isl_take isl_basic_map *bmap) | ||||||||||||
1500 | { | ||||||||||||
1501 | bmap = remove_redundant_divs(bmap); | ||||||||||||
1502 | bmap = isl_basic_map_mark_final(bmap); | ||||||||||||
1503 | return bmap; | ||||||||||||
1504 | } | ||||||||||||
1505 | |||||||||||||
1506 | struct isl_basic_setisl_basic_map *isl_basic_set_finalize(struct isl_basic_setisl_basic_map *bset) | ||||||||||||
1507 | { | ||||||||||||
1508 | return bset_from_bmap(isl_basic_map_finalize(bset_to_bmap(bset))); | ||||||||||||
1509 | } | ||||||||||||
1510 | |||||||||||||
1511 | /* Remove definition of any div that is defined in terms of the given variable. | ||||||||||||
1512 | * The div itself is not removed. Functions such as | ||||||||||||
1513 | * eliminate_divs_ineq depend on the other divs remaining in place. | ||||||||||||
1514 | */ | ||||||||||||
1515 | static __isl_give isl_basic_map *remove_dependent_vars( | ||||||||||||
1516 | __isl_take isl_basic_map *bmap, int pos) | ||||||||||||
1517 | { | ||||||||||||
1518 | int i; | ||||||||||||
1519 | |||||||||||||
1520 | if (!bmap) | ||||||||||||
1521 | return NULL((void*)0); | ||||||||||||
1522 | |||||||||||||
1523 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
1524 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
1525 | continue; | ||||||||||||
1526 | if (isl_int_is_zero(bmap->div[i][1+1+pos])(isl_sioimath_sgn(*(bmap->div[i][1+1+pos])) == 0)) | ||||||||||||
1527 | continue; | ||||||||||||
1528 | bmap = isl_basic_map_mark_div_unknown(bmap, i); | ||||||||||||
1529 | if (!bmap) | ||||||||||||
1530 | return NULL((void*)0); | ||||||||||||
1531 | } | ||||||||||||
1532 | return bmap; | ||||||||||||
1533 | } | ||||||||||||
1534 | |||||||||||||
1535 | /* Eliminate the specified variables from the constraints using | ||||||||||||
1536 | * Fourier-Motzkin. The variables themselves are not removed. | ||||||||||||
1537 | */ | ||||||||||||
1538 | __isl_give isl_basic_map *isl_basic_map_eliminate_vars( | ||||||||||||
1539 | __isl_take isl_basic_map *bmap, unsigned pos, unsigned n) | ||||||||||||
1540 | { | ||||||||||||
1541 | int d; | ||||||||||||
1542 | int i, j, k; | ||||||||||||
1543 | unsigned total; | ||||||||||||
1544 | int need_gauss = 0; | ||||||||||||
1545 | |||||||||||||
1546 | if (n == 0) | ||||||||||||
1547 | return bmap; | ||||||||||||
1548 | if (!bmap) | ||||||||||||
1549 | return NULL((void*)0); | ||||||||||||
1550 | total = isl_basic_map_total_dim(bmap); | ||||||||||||
1551 | |||||||||||||
1552 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
1553 | for (d = pos + n - 1; d >= 0 && d >= pos; --d) | ||||||||||||
1554 | bmap = remove_dependent_vars(bmap, d); | ||||||||||||
1555 | if (!bmap) | ||||||||||||
1556 | return NULL((void*)0); | ||||||||||||
1557 | |||||||||||||
1558 | for (d = pos + n - 1; | ||||||||||||
1559 | d >= 0 && d >= total - bmap->n_div && d >= pos; --d) | ||||||||||||
1560 | isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total); | ||||||||||||
1561 | for (d = pos + n - 1; d >= 0 && d >= pos; --d) { | ||||||||||||
1562 | int n_lower, n_upper; | ||||||||||||
1563 | if (!bmap) | ||||||||||||
1564 | return NULL((void*)0); | ||||||||||||
1565 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
1566 | if (isl_int_is_zero(bmap->eq[i][1+d])(isl_sioimath_sgn(*(bmap->eq[i][1+d])) == 0)) | ||||||||||||
1567 | continue; | ||||||||||||
1568 | eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL((void*)0)); | ||||||||||||
1569 | isl_basic_map_drop_equality(bmap, i); | ||||||||||||
1570 | need_gauss = 1; | ||||||||||||
1571 | break; | ||||||||||||
1572 | } | ||||||||||||
1573 | if (i < bmap->n_eq) | ||||||||||||
1574 | continue; | ||||||||||||
1575 | n_lower = 0; | ||||||||||||
1576 | n_upper = 0; | ||||||||||||
1577 | for (i = 0; i < bmap->n_ineq; ++i) { | ||||||||||||
1578 | if (isl_int_is_pos(bmap->ineq[i][1+d])(isl_sioimath_sgn(*(bmap->ineq[i][1+d])) > 0)) | ||||||||||||
1579 | n_lower++; | ||||||||||||
1580 | else if (isl_int_is_neg(bmap->ineq[i][1+d])(isl_sioimath_sgn(*(bmap->ineq[i][1+d])) < 0)) | ||||||||||||
1581 | n_upper++; | ||||||||||||
1582 | } | ||||||||||||
1583 | bmap = isl_basic_map_extend_constraints(bmap, | ||||||||||||
1584 | 0, n_lower * n_upper); | ||||||||||||
1585 | if (!bmap) | ||||||||||||
1586 | goto error; | ||||||||||||
1587 | for (i = bmap->n_ineq - 1; i >= 0; --i) { | ||||||||||||
1588 | int last; | ||||||||||||
1589 | if (isl_int_is_zero(bmap->ineq[i][1+d])(isl_sioimath_sgn(*(bmap->ineq[i][1+d])) == 0)) | ||||||||||||
1590 | continue; | ||||||||||||
1591 | last = -1; | ||||||||||||
1592 | for (j = 0; j < i; ++j) { | ||||||||||||
1593 | if (isl_int_is_zero(bmap->ineq[j][1+d])(isl_sioimath_sgn(*(bmap->ineq[j][1+d])) == 0)) | ||||||||||||
1594 | continue; | ||||||||||||
1595 | last = j; | ||||||||||||
1596 | if (isl_int_sgn(bmap->ineq[i][1+d])isl_sioimath_sgn(*(bmap->ineq[i][1+d])) == | ||||||||||||
1597 | isl_int_sgn(bmap->ineq[j][1+d])isl_sioimath_sgn(*(bmap->ineq[j][1+d]))) | ||||||||||||
1598 | continue; | ||||||||||||
1599 | k = isl_basic_map_alloc_inequality(bmap); | ||||||||||||
1600 | if (k < 0) | ||||||||||||
1601 | goto error; | ||||||||||||
1602 | isl_seq_cpy(bmap->ineq[k], bmap->ineq[i], | ||||||||||||
1603 | 1+total); | ||||||||||||
1604 | isl_seq_elim(bmap->ineq[k], bmap->ineq[j], | ||||||||||||
1605 | 1+d, 1+total, NULL((void*)0)); | ||||||||||||
1606 | } | ||||||||||||
1607 | isl_basic_map_drop_inequality(bmap, i); | ||||||||||||
1608 | i = last + 1; | ||||||||||||
1609 | } | ||||||||||||
1610 | if (n_lower > 0 && n_upper > 0) { | ||||||||||||
1611 | bmap = isl_basic_map_normalize_constraints(bmap); | ||||||||||||
1612 | bmap = isl_basic_map_remove_duplicate_constraints(bmap, | ||||||||||||
1613 | NULL((void*)0), 0); | ||||||||||||
1614 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
1615 | bmap = isl_basic_map_remove_redundancies(bmap); | ||||||||||||
1616 | need_gauss = 0; | ||||||||||||
1617 | if (!bmap) | ||||||||||||
1618 | goto error; | ||||||||||||
1619 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)(!!(((bmap)->flags) & ((1 << 1))))) | ||||||||||||
1620 | break; | ||||||||||||
1621 | } | ||||||||||||
1622 | } | ||||||||||||
1623 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED)(((bmap)->flags) &= ~((1 << 5))); | ||||||||||||
1624 | if (need_gauss) | ||||||||||||
1625 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
1626 | return bmap; | ||||||||||||
1627 | error: | ||||||||||||
1628 | isl_basic_map_free(bmap); | ||||||||||||
1629 | return NULL((void*)0); | ||||||||||||
1630 | } | ||||||||||||
1631 | |||||||||||||
1632 | struct isl_basic_setisl_basic_map *isl_basic_set_eliminate_vars( | ||||||||||||
1633 | struct isl_basic_setisl_basic_map *bset, unsigned pos, unsigned n) | ||||||||||||
1634 | { | ||||||||||||
1635 | return bset_from_bmap(isl_basic_map_eliminate_vars(bset_to_bmap(bset), | ||||||||||||
1636 | pos, n)); | ||||||||||||
1637 | } | ||||||||||||
1638 | |||||||||||||
1639 | /* Eliminate the specified n dimensions starting at first from the | ||||||||||||
1640 | * constraints, without removing the dimensions from the space. | ||||||||||||
1641 | * If the set is rational, the dimensions are eliminated using Fourier-Motzkin. | ||||||||||||
1642 | * Otherwise, they are projected out and the original space is restored. | ||||||||||||
1643 | */ | ||||||||||||
1644 | __isl_give isl_basic_map *isl_basic_map_eliminate( | ||||||||||||
1645 | __isl_take isl_basic_map *bmap, | ||||||||||||
1646 | enum isl_dim_type type, unsigned first, unsigned n) | ||||||||||||
1647 | { | ||||||||||||
1648 | isl_space *space; | ||||||||||||
1649 | |||||||||||||
1650 | if (!bmap) | ||||||||||||
1651 | return NULL((void*)0); | ||||||||||||
1652 | if (n == 0) | ||||||||||||
1653 | return bmap; | ||||||||||||
1654 | |||||||||||||
1655 | if (first + n > isl_basic_map_dim(bmap, type) || first + n < first) | ||||||||||||
1656 | isl_die(bmap->ctx, isl_error_invalid,do { isl_handle_error(bmap->ctx, isl_error_invalid, "index out of bounds" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 1657); goto error; } while (0) | ||||||||||||
1657 | "index out of bounds", goto error)do { isl_handle_error(bmap->ctx, isl_error_invalid, "index out of bounds" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 1657); goto error; } while (0); | ||||||||||||
1658 | |||||||||||||
1659 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)(!!(((bmap)->flags) & ((1 << 4))))) { | ||||||||||||
1660 | first += isl_basic_map_offset(bmap, type) - 1; | ||||||||||||
1661 | bmap = isl_basic_map_eliminate_vars(bmap, first, n); | ||||||||||||
1662 | return isl_basic_map_finalize(bmap); | ||||||||||||
1663 | } | ||||||||||||
1664 | |||||||||||||
1665 | space = isl_basic_map_get_space(bmap); | ||||||||||||
1666 | bmap = isl_basic_map_project_out(bmap, type, first, n); | ||||||||||||
1667 | bmap = isl_basic_map_insert_dims(bmap, type, first, n); | ||||||||||||
1668 | bmap = isl_basic_map_reset_space(bmap, space); | ||||||||||||
1669 | return bmap; | ||||||||||||
1670 | error: | ||||||||||||
1671 | isl_basic_map_free(bmap); | ||||||||||||
1672 | return NULL((void*)0); | ||||||||||||
1673 | } | ||||||||||||
1674 | |||||||||||||
1675 | __isl_give isl_basic_setisl_basic_map *isl_basic_set_eliminate( | ||||||||||||
1676 | __isl_take isl_basic_setisl_basic_map *bset, | ||||||||||||
1677 | enum isl_dim_type type, unsigned first, unsigned n) | ||||||||||||
1678 | { | ||||||||||||
1679 | return isl_basic_map_eliminate(bset, type, first, n); | ||||||||||||
1680 | } | ||||||||||||
1681 | |||||||||||||
1682 | /* Remove all constraints from "bmap" that reference any unknown local | ||||||||||||
1683 | * variables (directly or indirectly). | ||||||||||||
1684 | * | ||||||||||||
1685 | * Dropping all constraints on a local variable will make it redundant, | ||||||||||||
1686 | * so it will get removed implicitly by | ||||||||||||
1687 | * isl_basic_map_drop_constraints_involving_dims. Some other local | ||||||||||||
1688 | * variables may also end up becoming redundant if they only appear | ||||||||||||
1689 | * in constraints together with the unknown local variable. | ||||||||||||
1690 | * Therefore, start over after calling | ||||||||||||
1691 | * isl_basic_map_drop_constraints_involving_dims. | ||||||||||||
1692 | */ | ||||||||||||
1693 | __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs( | ||||||||||||
1694 | __isl_take isl_basic_map *bmap) | ||||||||||||
1695 | { | ||||||||||||
1696 | isl_bool known; | ||||||||||||
1697 | int i, n_div, o_div; | ||||||||||||
1698 | |||||||||||||
1699 | known = isl_basic_map_divs_known(bmap); | ||||||||||||
1700 | if (known < 0) | ||||||||||||
1701 | return isl_basic_map_free(bmap); | ||||||||||||
1702 | if (known) | ||||||||||||
1703 | return bmap; | ||||||||||||
1704 | |||||||||||||
1705 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
1706 | o_div = isl_basic_map_offset(bmap, isl_dim_div) - 1; | ||||||||||||
1707 | |||||||||||||
1708 | for (i = 0; i < n_div; ++i) { | ||||||||||||
1709 | known = isl_basic_map_div_is_known(bmap, i); | ||||||||||||
1710 | if (known < 0) | ||||||||||||
1711 | return isl_basic_map_free(bmap); | ||||||||||||
1712 | if (known) | ||||||||||||
1713 | continue; | ||||||||||||
1714 | bmap = remove_dependent_vars(bmap, o_div + i); | ||||||||||||
1715 | bmap = isl_basic_map_drop_constraints_involving_dims(bmap, | ||||||||||||
1716 | isl_dim_div, i, 1); | ||||||||||||
1717 | if (!bmap) | ||||||||||||
1718 | return NULL((void*)0); | ||||||||||||
1719 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
1720 | i = -1; | ||||||||||||
1721 | } | ||||||||||||
1722 | |||||||||||||
1723 | return bmap; | ||||||||||||
1724 | } | ||||||||||||
1725 | |||||||||||||
1726 | /* Remove all constraints from "map" that reference any unknown local | ||||||||||||
1727 | * variables (directly or indirectly). | ||||||||||||
1728 | * | ||||||||||||
1729 | * Since constraints may get dropped from the basic maps, | ||||||||||||
1730 | * they may no longer be disjoint from each other. | ||||||||||||
1731 | */ | ||||||||||||
1732 | __isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs( | ||||||||||||
1733 | __isl_take isl_map *map) | ||||||||||||
1734 | { | ||||||||||||
1735 | int i; | ||||||||||||
1736 | isl_bool known; | ||||||||||||
1737 | |||||||||||||
1738 | known = isl_map_divs_known(map); | ||||||||||||
1739 | if (known < 0) | ||||||||||||
1740 | return isl_map_free(map); | ||||||||||||
1741 | if (known) | ||||||||||||
1742 | return map; | ||||||||||||
1743 | |||||||||||||
1744 | map = isl_map_cow(map); | ||||||||||||
1745 | if (!map) | ||||||||||||
1746 | return NULL((void*)0); | ||||||||||||
1747 | |||||||||||||
1748 | for (i = 0; i < map->n; ++i) { | ||||||||||||
1749 | map->p[i] = | ||||||||||||
1750 | isl_basic_map_drop_constraint_involving_unknown_divs( | ||||||||||||
1751 | map->p[i]); | ||||||||||||
1752 | if (!map->p[i]) | ||||||||||||
1753 | return isl_map_free(map); | ||||||||||||
1754 | } | ||||||||||||
1755 | |||||||||||||
1756 | if (map->n > 1) | ||||||||||||
1757 | ISL_F_CLR(map, ISL_MAP_DISJOINT)(((map)->flags) &= ~((1 << 0))); | ||||||||||||
1758 | |||||||||||||
1759 | return map; | ||||||||||||
1760 | } | ||||||||||||
1761 | |||||||||||||
1762 | /* Don't assume equalities are in order, because align_divs | ||||||||||||
1763 | * may have changed the order of the divs. | ||||||||||||
1764 | */ | ||||||||||||
1765 | static void compute_elimination_index(__isl_keep isl_basic_map *bmap, int *elim) | ||||||||||||
1766 | { | ||||||||||||
1767 | int d, i; | ||||||||||||
1768 | unsigned total; | ||||||||||||
1769 | |||||||||||||
1770 | total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1771 | for (d = 0; d < total; ++d) | ||||||||||||
1772 | elim[d] = -1; | ||||||||||||
1773 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
1774 | for (d = total - 1; d >= 0; --d) { | ||||||||||||
1775 | if (isl_int_is_zero(bmap->eq[i][1+d])(isl_sioimath_sgn(*(bmap->eq[i][1+d])) == 0)) | ||||||||||||
1776 | continue; | ||||||||||||
1777 | elim[d] = i; | ||||||||||||
1778 | break; | ||||||||||||
1779 | } | ||||||||||||
1780 | } | ||||||||||||
1781 | } | ||||||||||||
1782 | |||||||||||||
1783 | static void set_compute_elimination_index(__isl_keep isl_basic_setisl_basic_map *bset, | ||||||||||||
1784 | int *elim) | ||||||||||||
1785 | { | ||||||||||||
1786 | compute_elimination_index(bset_to_bmap(bset), elim); | ||||||||||||
1787 | } | ||||||||||||
1788 | |||||||||||||
1789 | static int reduced_using_equalities(isl_int *dst, isl_int *src, | ||||||||||||
1790 | __isl_keep isl_basic_map *bmap, int *elim) | ||||||||||||
1791 | { | ||||||||||||
1792 | int d; | ||||||||||||
1793 | int copied = 0; | ||||||||||||
1794 | unsigned total; | ||||||||||||
1795 | |||||||||||||
1796 | total = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
1797 | for (d = total - 1; d >= 0; --d) { | ||||||||||||
1798 | if (isl_int_is_zero(src[1+d])(isl_sioimath_sgn(*(src[1+d])) == 0)) | ||||||||||||
1799 | continue; | ||||||||||||
1800 | if (elim[d] == -1) | ||||||||||||
1801 | continue; | ||||||||||||
1802 | if (!copied) { | ||||||||||||
1803 | isl_seq_cpy(dst, src, 1 + total); | ||||||||||||
1804 | copied = 1; | ||||||||||||
1805 | } | ||||||||||||
1806 | isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL((void*)0)); | ||||||||||||
1807 | } | ||||||||||||
1808 | return copied; | ||||||||||||
1809 | } | ||||||||||||
1810 | |||||||||||||
1811 | static int set_reduced_using_equalities(isl_int *dst, isl_int *src, | ||||||||||||
1812 | __isl_keep isl_basic_setisl_basic_map *bset, int *elim) | ||||||||||||
1813 | { | ||||||||||||
1814 | return reduced_using_equalities(dst, src, | ||||||||||||
1815 | bset_to_bmap(bset), elim); | ||||||||||||
1816 | } | ||||||||||||
1817 | |||||||||||||
1818 | static __isl_give isl_basic_setisl_basic_map *isl_basic_set_reduce_using_equalities( | ||||||||||||
1819 | __isl_take isl_basic_setisl_basic_map *bset, __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
1820 | { | ||||||||||||
1821 | int i; | ||||||||||||
1822 | int *elim; | ||||||||||||
1823 | |||||||||||||
1824 | if (!bset || !context) | ||||||||||||
1825 | goto error; | ||||||||||||
1826 | |||||||||||||
1827 | if (context->n_eq == 0) { | ||||||||||||
1828 | isl_basic_set_free(context); | ||||||||||||
1829 | return bset; | ||||||||||||
1830 | } | ||||||||||||
1831 | |||||||||||||
1832 | bset = isl_basic_set_cow(bset); | ||||||||||||
1833 | if (!bset) | ||||||||||||
1834 | goto error; | ||||||||||||
1835 | |||||||||||||
1836 | elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset))((int *)isl_malloc_or_die(bset->ctx, (isl_basic_set_n_dim( bset))*sizeof(int))); | ||||||||||||
1837 | if (!elim) | ||||||||||||
1838 | goto error; | ||||||||||||
1839 | set_compute_elimination_index(context, elim); | ||||||||||||
1840 | for (i = 0; i < bset->n_eq; ++i) | ||||||||||||
1841 | set_reduced_using_equalities(bset->eq[i], bset->eq[i], | ||||||||||||
1842 | context, elim); | ||||||||||||
1843 | for (i = 0; i < bset->n_ineq; ++i) | ||||||||||||
1844 | set_reduced_using_equalities(bset->ineq[i], bset->ineq[i], | ||||||||||||
1845 | context, elim); | ||||||||||||
1846 | isl_basic_set_free(context); | ||||||||||||
1847 | free(elim); | ||||||||||||
1848 | bset = isl_basic_set_simplify(bset); | ||||||||||||
1849 | bset = isl_basic_set_finalize(bset); | ||||||||||||
1850 | return bset; | ||||||||||||
1851 | error: | ||||||||||||
1852 | isl_basic_set_free(bset); | ||||||||||||
1853 | isl_basic_set_free(context); | ||||||||||||
1854 | return NULL((void*)0); | ||||||||||||
1855 | } | ||||||||||||
1856 | |||||||||||||
1857 | /* For each inequality in "ineq" that is a shifted (more relaxed) | ||||||||||||
1858 | * copy of an inequality in "context", mark the corresponding entry | ||||||||||||
1859 | * in "row" with -1. | ||||||||||||
1860 | * If an inequality only has a non-negative constant term, then | ||||||||||||
1861 | * mark it as well. | ||||||||||||
1862 | */ | ||||||||||||
1863 | static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq, | ||||||||||||
1864 | __isl_keep isl_basic_setisl_basic_map *context, int *row) | ||||||||||||
1865 | { | ||||||||||||
1866 | struct isl_constraint_index ci; | ||||||||||||
1867 | int n_ineq; | ||||||||||||
1868 | unsigned total; | ||||||||||||
1869 | int k; | ||||||||||||
1870 | |||||||||||||
1871 | if (!ineq || !context) | ||||||||||||
1872 | return isl_stat_error; | ||||||||||||
1873 | if (context->n_ineq == 0) | ||||||||||||
1874 | return isl_stat_ok; | ||||||||||||
1875 | if (setup_constraint_index(&ci, context) < 0) | ||||||||||||
1876 | return isl_stat_error; | ||||||||||||
1877 | |||||||||||||
1878 | n_ineq = isl_mat_rows(ineq); | ||||||||||||
1879 | total = isl_mat_cols(ineq) - 1; | ||||||||||||
1880 | for (k = 0; k < n_ineq; ++k) { | ||||||||||||
1881 | int l; | ||||||||||||
1882 | isl_bool redundant; | ||||||||||||
1883 | |||||||||||||
1884 | l = isl_seq_first_non_zero(ineq->row[k] + 1, total); | ||||||||||||
1885 | if (l < 0 && isl_int_is_nonneg(ineq->row[k][0])(isl_sioimath_sgn(*(ineq->row[k][0])) >= 0)) { | ||||||||||||
1886 | row[k] = -1; | ||||||||||||
1887 | continue; | ||||||||||||
1888 | } | ||||||||||||
1889 | redundant = constraint_index_is_redundant(&ci, ineq->row[k]); | ||||||||||||
1890 | if (redundant < 0) | ||||||||||||
1891 | goto error; | ||||||||||||
1892 | if (!redundant) | ||||||||||||
1893 | continue; | ||||||||||||
1894 | row[k] = -1; | ||||||||||||
1895 | } | ||||||||||||
1896 | constraint_index_free(&ci); | ||||||||||||
1897 | return isl_stat_ok; | ||||||||||||
1898 | error: | ||||||||||||
1899 | constraint_index_free(&ci); | ||||||||||||
1900 | return isl_stat_error; | ||||||||||||
1901 | } | ||||||||||||
1902 | |||||||||||||
1903 | static __isl_give isl_basic_setisl_basic_map *remove_shifted_constraints( | ||||||||||||
1904 | __isl_take isl_basic_setisl_basic_map *bset, __isl_keep isl_basic_setisl_basic_map *context) | ||||||||||||
1905 | { | ||||||||||||
1906 | struct isl_constraint_index ci; | ||||||||||||
1907 | int k; | ||||||||||||
1908 | |||||||||||||
1909 | if (!bset || !context) | ||||||||||||
1910 | return bset; | ||||||||||||
1911 | |||||||||||||
1912 | if (context->n_ineq == 0) | ||||||||||||
1913 | return bset; | ||||||||||||
1914 | if (setup_constraint_index(&ci, context) < 0) | ||||||||||||
1915 | return bset; | ||||||||||||
1916 | |||||||||||||
1917 | for (k = 0; k < bset->n_ineq; ++k) { | ||||||||||||
1918 | isl_bool redundant; | ||||||||||||
1919 | |||||||||||||
1920 | redundant = constraint_index_is_redundant(&ci, bset->ineq[k]); | ||||||||||||
1921 | if (redundant < 0) | ||||||||||||
1922 | goto error; | ||||||||||||
1923 | if (!redundant) | ||||||||||||
1924 | continue; | ||||||||||||
1925 | bset = isl_basic_set_cow(bset); | ||||||||||||
1926 | if (!bset) | ||||||||||||
1927 | goto error; | ||||||||||||
1928 | isl_basic_set_drop_inequality(bset, k); | ||||||||||||
1929 | --k; | ||||||||||||
1930 | } | ||||||||||||
1931 | constraint_index_free(&ci); | ||||||||||||
1932 | return bset; | ||||||||||||
1933 | error: | ||||||||||||
1934 | constraint_index_free(&ci); | ||||||||||||
1935 | return bset; | ||||||||||||
1936 | } | ||||||||||||
1937 | |||||||||||||
1938 | /* Remove constraints from "bmap" that are identical to constraints | ||||||||||||
1939 | * in "context" or that are more relaxed (greater constant term). | ||||||||||||
1940 | * | ||||||||||||
1941 | * We perform the test for shifted copies on the pure constraints | ||||||||||||
1942 | * in remove_shifted_constraints. | ||||||||||||
1943 | */ | ||||||||||||
1944 | static __isl_give isl_basic_map *isl_basic_map_remove_shifted_constraints( | ||||||||||||
1945 | __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context) | ||||||||||||
1946 | { | ||||||||||||
1947 | isl_basic_setisl_basic_map *bset, *bset_context; | ||||||||||||
1948 | |||||||||||||
1949 | if (!bmap || !context) | ||||||||||||
1950 | goto error; | ||||||||||||
1951 | |||||||||||||
1952 | if (bmap->n_ineq == 0 || context->n_ineq == 0) { | ||||||||||||
1953 | isl_basic_map_free(context); | ||||||||||||
1954 | return bmap; | ||||||||||||
1955 | } | ||||||||||||
1956 | |||||||||||||
1957 | context = isl_basic_map_align_divs(context, bmap); | ||||||||||||
1958 | bmap = isl_basic_map_align_divs(bmap, context); | ||||||||||||
1959 | |||||||||||||
1960 | bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); | ||||||||||||
1961 | bset_context = isl_basic_map_underlying_set(context); | ||||||||||||
1962 | bset = remove_shifted_constraints(bset, bset_context); | ||||||||||||
1963 | isl_basic_set_free(bset_context); | ||||||||||||
1964 | |||||||||||||
1965 | bmap = isl_basic_map_overlying_set(bset, bmap); | ||||||||||||
1966 | |||||||||||||
1967 | return bmap; | ||||||||||||
1968 | error: | ||||||||||||
1969 | isl_basic_map_free(bmap); | ||||||||||||
1970 | isl_basic_map_free(context); | ||||||||||||
1971 | return NULL((void*)0); | ||||||||||||
1972 | } | ||||||||||||
1973 | |||||||||||||
1974 | /* Does the (linear part of a) constraint "c" involve any of the "len" | ||||||||||||
1975 | * "relevant" dimensions? | ||||||||||||
1976 | */ | ||||||||||||
1977 | static int is_related(isl_int *c, int len, int *relevant) | ||||||||||||
1978 | { | ||||||||||||
1979 | int i; | ||||||||||||
1980 | |||||||||||||
1981 | for (i = 0; i < len; ++i) { | ||||||||||||
1982 | if (!relevant[i]) | ||||||||||||
1983 | continue; | ||||||||||||
1984 | if (!isl_int_is_zero(c[i])(isl_sioimath_sgn(*(c[i])) == 0)) | ||||||||||||
1985 | return 1; | ||||||||||||
1986 | } | ||||||||||||
1987 | |||||||||||||
1988 | return 0; | ||||||||||||
1989 | } | ||||||||||||
1990 | |||||||||||||
1991 | /* Drop constraints from "bmap" that do not involve any of | ||||||||||||
1992 | * the dimensions marked "relevant". | ||||||||||||
1993 | */ | ||||||||||||
1994 | static __isl_give isl_basic_map *drop_unrelated_constraints( | ||||||||||||
1995 | __isl_take isl_basic_map *bmap, int *relevant) | ||||||||||||
1996 | { | ||||||||||||
1997 | int i, dim; | ||||||||||||
1998 | |||||||||||||
1999 | dim = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
2000 | for (i = 0; i < dim; ++i) | ||||||||||||
2001 | if (!relevant[i]) | ||||||||||||
2002 | break; | ||||||||||||
2003 | if (i >= dim) | ||||||||||||
2004 | return bmap; | ||||||||||||
2005 | |||||||||||||
2006 | for (i = bmap->n_eq - 1; i >= 0; --i) | ||||||||||||
2007 | if (!is_related(bmap->eq[i] + 1, dim, relevant)) { | ||||||||||||
2008 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
2009 | if (isl_basic_map_drop_equality(bmap, i) < 0) | ||||||||||||
2010 | return isl_basic_map_free(bmap); | ||||||||||||
2011 | } | ||||||||||||
2012 | |||||||||||||
2013 | for (i = bmap->n_ineq - 1; i >= 0; --i) | ||||||||||||
2014 | if (!is_related(bmap->ineq[i] + 1, dim, relevant)) { | ||||||||||||
2015 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
2016 | if (isl_basic_map_drop_inequality(bmap, i) < 0) | ||||||||||||
2017 | return isl_basic_map_free(bmap); | ||||||||||||
2018 | } | ||||||||||||
2019 | |||||||||||||
2020 | return bmap; | ||||||||||||
2021 | } | ||||||||||||
2022 | |||||||||||||
2023 | /* Update the groups in "group" based on the (linear part of a) constraint "c". | ||||||||||||
2024 | * | ||||||||||||
2025 | * In particular, for any variable involved in the constraint, | ||||||||||||
2026 | * find the actual group id from before and replace the group | ||||||||||||
2027 | * of the corresponding variable by the minimal group of all | ||||||||||||
2028 | * the variables involved in the constraint considered so far | ||||||||||||
2029 | * (if this minimum is smaller) or replace the minimum by this group | ||||||||||||
2030 | * (if the minimum is larger). | ||||||||||||
2031 | * | ||||||||||||
2032 | * At the end, all the variables in "c" will (indirectly) point | ||||||||||||
2033 | * to the minimal of the groups that they referred to originally. | ||||||||||||
2034 | */ | ||||||||||||
2035 | static void update_groups(int dim, int *group, isl_int *c) | ||||||||||||
2036 | { | ||||||||||||
2037 | int j; | ||||||||||||
2038 | int min = dim; | ||||||||||||
2039 | |||||||||||||
2040 | for (j = 0; j < dim; ++j) { | ||||||||||||
2041 | if (isl_int_is_zero(c[j])(isl_sioimath_sgn(*(c[j])) == 0)) | ||||||||||||
2042 | continue; | ||||||||||||
2043 | while (group[j] >= 0 && group[group[j]] != group[j]) | ||||||||||||
2044 | group[j] = group[group[j]]; | ||||||||||||
2045 | if (group[j] == min) | ||||||||||||
2046 | continue; | ||||||||||||
2047 | if (group[j] < min) { | ||||||||||||
2048 | if (min >= 0 && min < dim) | ||||||||||||
2049 | group[min] = group[j]; | ||||||||||||
2050 | min = group[j]; | ||||||||||||
2051 | } else | ||||||||||||
2052 | group[group[j]] = min; | ||||||||||||
2053 | } | ||||||||||||
2054 | } | ||||||||||||
2055 | |||||||||||||
2056 | /* Allocate an array of groups of variables, one for each variable | ||||||||||||
2057 | * in "context", initialized to zero. | ||||||||||||
2058 | */ | ||||||||||||
2059 | static int *alloc_groups(__isl_keep isl_basic_setisl_basic_map *context) | ||||||||||||
2060 | { | ||||||||||||
2061 | isl_ctx *ctx; | ||||||||||||
2062 | int dim; | ||||||||||||
2063 | |||||||||||||
2064 | dim = isl_basic_set_dim(context, isl_dim_set); | ||||||||||||
2065 | ctx = isl_basic_set_get_ctx(context); | ||||||||||||
2066 | return isl_calloc_array(ctx, int, dim)((int *)isl_calloc_or_die(ctx, dim, sizeof(int))); | ||||||||||||
2067 | } | ||||||||||||
2068 | |||||||||||||
2069 | /* Drop constraints from "bmap" that only involve variables that are | ||||||||||||
2070 | * not related to any of the variables marked with a "-1" in "group". | ||||||||||||
2071 | * | ||||||||||||
2072 | * We construct groups of variables that collect variables that | ||||||||||||
2073 | * (indirectly) appear in some common constraint of "bmap". | ||||||||||||
2074 | * Each group is identified by the first variable in the group, | ||||||||||||
2075 | * except for the special group of variables that was already identified | ||||||||||||
2076 | * in the input as -1 (or are related to those variables). | ||||||||||||
2077 | * If group[i] is equal to i (or -1), then the group of i is i (or -1), | ||||||||||||
2078 | * otherwise the group of i is the group of group[i]. | ||||||||||||
2079 | * | ||||||||||||
2080 | * We first initialize groups for the remaining variables. | ||||||||||||
2081 | * Then we iterate over the constraints of "bmap" and update the | ||||||||||||
2082 | * group of the variables in the constraint by the smallest group. | ||||||||||||
2083 | * Finally, we resolve indirect references to groups by running over | ||||||||||||
2084 | * the variables. | ||||||||||||
2085 | * | ||||||||||||
2086 | * After computing the groups, we drop constraints that do not involve | ||||||||||||
2087 | * any variables in the -1 group. | ||||||||||||
2088 | */ | ||||||||||||
2089 | __isl_give isl_basic_map *isl_basic_map_drop_unrelated_constraints( | ||||||||||||
2090 | __isl_take isl_basic_map *bmap, __isl_take int *group) | ||||||||||||
2091 | { | ||||||||||||
2092 | int dim; | ||||||||||||
2093 | int i; | ||||||||||||
2094 | int last; | ||||||||||||
2095 | |||||||||||||
2096 | if (!bmap) | ||||||||||||
2097 | return NULL((void*)0); | ||||||||||||
2098 | |||||||||||||
2099 | dim = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
2100 | |||||||||||||
2101 | last = -1; | ||||||||||||
2102 | for (i = 0; i < dim; ++i) | ||||||||||||
2103 | if (group[i] >= 0) | ||||||||||||
2104 | last = group[i] = i; | ||||||||||||
2105 | if (last < 0) { | ||||||||||||
2106 | free(group); | ||||||||||||
2107 | return bmap; | ||||||||||||
2108 | } | ||||||||||||
2109 | |||||||||||||
2110 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
2111 | update_groups(dim, group, bmap->eq[i] + 1); | ||||||||||||
2112 | for (i = 0; i < bmap->n_ineq; ++i) | ||||||||||||
2113 | update_groups(dim, group, bmap->ineq[i] + 1); | ||||||||||||
2114 | |||||||||||||
2115 | for (i = 0; i < dim; ++i) | ||||||||||||
2116 | if (group[i] >= 0) | ||||||||||||
2117 | group[i] = group[group[i]]; | ||||||||||||
2118 | |||||||||||||
2119 | for (i = 0; i < dim; ++i) | ||||||||||||
2120 | group[i] = group[i] == -1; | ||||||||||||
2121 | |||||||||||||
2122 | bmap = drop_unrelated_constraints(bmap, group); | ||||||||||||
2123 | |||||||||||||
2124 | free(group); | ||||||||||||
2125 | return bmap; | ||||||||||||
2126 | } | ||||||||||||
2127 | |||||||||||||
2128 | /* Drop constraints from "context" that are irrelevant for computing | ||||||||||||
2129 | * the gist of "bset". | ||||||||||||
2130 | * | ||||||||||||
2131 | * In particular, drop constraints in variables that are not related | ||||||||||||
2132 | * to any of the variables involved in the constraints of "bset" | ||||||||||||
2133 | * in the sense that there is no sequence of constraints that connects them. | ||||||||||||
2134 | * | ||||||||||||
2135 | * We first mark all variables that appear in "bset" as belonging | ||||||||||||
2136 | * to a "-1" group and then continue with group_and_drop_irrelevant_constraints. | ||||||||||||
2137 | */ | ||||||||||||
2138 | static __isl_give isl_basic_setisl_basic_map *drop_irrelevant_constraints( | ||||||||||||
2139 | __isl_take isl_basic_setisl_basic_map *context, __isl_keep isl_basic_setisl_basic_map *bset) | ||||||||||||
2140 | { | ||||||||||||
2141 | int *group; | ||||||||||||
2142 | int dim; | ||||||||||||
2143 | int i, j; | ||||||||||||
2144 | |||||||||||||
2145 | if (!context || !bset) | ||||||||||||
2146 | return isl_basic_set_free(context); | ||||||||||||
2147 | |||||||||||||
2148 | group = alloc_groups(context); | ||||||||||||
2149 | |||||||||||||
2150 | if (!group) | ||||||||||||
2151 | return isl_basic_set_free(context); | ||||||||||||
2152 | |||||||||||||
2153 | dim = isl_basic_set_dim(bset, isl_dim_set); | ||||||||||||
2154 | for (i = 0; i < dim; ++i) { | ||||||||||||
2155 | for (j = 0; j < bset->n_eq; ++j) | ||||||||||||
2156 | if (!isl_int_is_zero(bset->eq[j][1 + i])(isl_sioimath_sgn(*(bset->eq[j][1 + i])) == 0)) | ||||||||||||
2157 | break; | ||||||||||||
2158 | if (j < bset->n_eq) { | ||||||||||||
2159 | group[i] = -1; | ||||||||||||
2160 | continue; | ||||||||||||
2161 | } | ||||||||||||
2162 | for (j = 0; j < bset->n_ineq; ++j) | ||||||||||||
2163 | if (!isl_int_is_zero(bset->ineq[j][1 + i])(isl_sioimath_sgn(*(bset->ineq[j][1 + i])) == 0)) | ||||||||||||
2164 | break; | ||||||||||||
2165 | if (j < bset->n_ineq) | ||||||||||||
2166 | group[i] = -1; | ||||||||||||
2167 | } | ||||||||||||
2168 | |||||||||||||
2169 | return isl_basic_map_drop_unrelated_constraints(context, group); | ||||||||||||
2170 | } | ||||||||||||
2171 | |||||||||||||
2172 | /* Drop constraints from "context" that are irrelevant for computing | ||||||||||||
2173 | * the gist of the inequalities "ineq". | ||||||||||||
2174 | * Inequalities in "ineq" for which the corresponding element of row | ||||||||||||
2175 | * is set to -1 have already been marked for removal and should be ignored. | ||||||||||||
2176 | * | ||||||||||||
2177 | * In particular, drop constraints in variables that are not related | ||||||||||||
2178 | * to any of the variables involved in "ineq" | ||||||||||||
2179 | * in the sense that there is no sequence of constraints that connects them. | ||||||||||||
2180 | * | ||||||||||||
2181 | * We first mark all variables that appear in "bset" as belonging | ||||||||||||
2182 | * to a "-1" group and then continue with group_and_drop_irrelevant_constraints. | ||||||||||||
2183 | */ | ||||||||||||
2184 | static __isl_give isl_basic_setisl_basic_map *drop_irrelevant_constraints_marked( | ||||||||||||
2185 | __isl_take isl_basic_setisl_basic_map *context, __isl_keep isl_mat *ineq, int *row) | ||||||||||||
2186 | { | ||||||||||||
2187 | int *group; | ||||||||||||
2188 | int dim; | ||||||||||||
2189 | int i, j, n; | ||||||||||||
2190 | |||||||||||||
2191 | if (!context || !ineq) | ||||||||||||
2192 | return isl_basic_set_free(context); | ||||||||||||
2193 | |||||||||||||
2194 | group = alloc_groups(context); | ||||||||||||
2195 | |||||||||||||
2196 | if (!group) | ||||||||||||
2197 | return isl_basic_set_free(context); | ||||||||||||
2198 | |||||||||||||
2199 | dim = isl_basic_set_dim(context, isl_dim_set); | ||||||||||||
2200 | n = isl_mat_rows(ineq); | ||||||||||||
2201 | for (i = 0; i < dim; ++i) { | ||||||||||||
2202 | for (j = 0; j < n; ++j) { | ||||||||||||
2203 | if (row[j] < 0) | ||||||||||||
2204 | continue; | ||||||||||||
2205 | if (!isl_int_is_zero(ineq->row[j][1 + i])(isl_sioimath_sgn(*(ineq->row[j][1 + i])) == 0)) | ||||||||||||
2206 | break; | ||||||||||||
2207 | } | ||||||||||||
2208 | if (j < n) | ||||||||||||
2209 | group[i] = -1; | ||||||||||||
2210 | } | ||||||||||||
2211 | |||||||||||||
2212 | return isl_basic_map_drop_unrelated_constraints(context, group); | ||||||||||||
2213 | } | ||||||||||||
2214 | |||||||||||||
2215 | /* Do all "n" entries of "row" contain a negative value? | ||||||||||||
2216 | */ | ||||||||||||
2217 | static int all_neg(int *row, int n) | ||||||||||||
2218 | { | ||||||||||||
2219 | int i; | ||||||||||||
2220 | |||||||||||||
2221 | for (i = 0; i < n; ++i) | ||||||||||||
2222 | if (row[i] >= 0) | ||||||||||||
2223 | return 0; | ||||||||||||
2224 | |||||||||||||
2225 | return 1; | ||||||||||||
2226 | } | ||||||||||||
2227 | |||||||||||||
2228 | /* Update the inequalities in "bset" based on the information in "row" | ||||||||||||
2229 | * and "tab". | ||||||||||||
2230 | * | ||||||||||||
2231 | * In particular, the array "row" contains either -1, meaning that | ||||||||||||
2232 | * the corresponding inequality of "bset" is redundant, or the index | ||||||||||||
2233 | * of an inequality in "tab". | ||||||||||||
2234 | * | ||||||||||||
2235 | * If the row entry is -1, then drop the inequality. | ||||||||||||
2236 | * Otherwise, if the constraint is marked redundant in the tableau, | ||||||||||||
2237 | * then drop the inequality. Similarly, if it is marked as an equality | ||||||||||||
2238 | * in the tableau, then turn the inequality into an equality and | ||||||||||||
2239 | * perform Gaussian elimination. | ||||||||||||
2240 | */ | ||||||||||||
2241 | static __isl_give isl_basic_setisl_basic_map *update_ineq(__isl_take isl_basic_setisl_basic_map *bset, | ||||||||||||
2242 | __isl_keep int *row, struct isl_tab *tab) | ||||||||||||
2243 | { | ||||||||||||
2244 | int i; | ||||||||||||
2245 | unsigned n_ineq; | ||||||||||||
2246 | unsigned n_eq; | ||||||||||||
2247 | int found_equality = 0; | ||||||||||||
2248 | |||||||||||||
2249 | if (!bset) | ||||||||||||
2250 | return NULL((void*)0); | ||||||||||||
2251 | if (tab && tab->empty) | ||||||||||||
2252 | return isl_basic_set_set_to_empty(bset); | ||||||||||||
2253 | |||||||||||||
2254 | n_ineq = bset->n_ineq; | ||||||||||||
2255 | for (i = n_ineq - 1; i >= 0; --i) { | ||||||||||||
2256 | if (row[i] < 0) { | ||||||||||||
2257 | if (isl_basic_set_drop_inequality(bset, i) < 0) | ||||||||||||
2258 | return isl_basic_set_free(bset); | ||||||||||||
2259 | continue; | ||||||||||||
2260 | } | ||||||||||||
2261 | if (!tab) | ||||||||||||
2262 | continue; | ||||||||||||
2263 | n_eq = tab->n_eq; | ||||||||||||
2264 | if (isl_tab_is_equality(tab, n_eq + row[i])) { | ||||||||||||
2265 | isl_basic_map_inequality_to_equality(bset, i); | ||||||||||||
2266 | found_equality = 1; | ||||||||||||
2267 | } else if (isl_tab_is_redundant(tab, n_eq + row[i])) { | ||||||||||||
2268 | if (isl_basic_set_drop_inequality(bset, i) < 0) | ||||||||||||
2269 | return isl_basic_set_free(bset); | ||||||||||||
2270 | } | ||||||||||||
2271 | } | ||||||||||||
2272 | |||||||||||||
2273 | if (found_equality) | ||||||||||||
2274 | bset = isl_basic_set_gauss(bset, NULL((void*)0)); | ||||||||||||
2275 | bset = isl_basic_set_finalize(bset); | ||||||||||||
2276 | return bset; | ||||||||||||
2277 | } | ||||||||||||
2278 | |||||||||||||
2279 | /* Update the inequalities in "bset" based on the information in "row" | ||||||||||||
2280 | * and "tab" and free all arguments (other than "bset"). | ||||||||||||
2281 | */ | ||||||||||||
2282 | static __isl_give isl_basic_setisl_basic_map *update_ineq_free( | ||||||||||||
2283 | __isl_take isl_basic_setisl_basic_map *bset, __isl_take isl_mat *ineq, | ||||||||||||
2284 | __isl_take isl_basic_setisl_basic_map *context, __isl_take int *row, | ||||||||||||
2285 | struct isl_tab *tab) | ||||||||||||
2286 | { | ||||||||||||
2287 | isl_mat_free(ineq); | ||||||||||||
2288 | isl_basic_set_free(context); | ||||||||||||
2289 | |||||||||||||
2290 | bset = update_ineq(bset, row, tab); | ||||||||||||
2291 | |||||||||||||
2292 | free(row); | ||||||||||||
2293 | isl_tab_free(tab); | ||||||||||||
2294 | return bset; | ||||||||||||
2295 | } | ||||||||||||
2296 | |||||||||||||
2297 | /* Remove all information from bset that is redundant in the context | ||||||||||||
2298 | * of context. | ||||||||||||
2299 | * "ineq" contains the (possibly transformed) inequalities of "bset", | ||||||||||||
2300 | * in the same order. | ||||||||||||
2301 | * The (explicit) equalities of "bset" are assumed to have been taken | ||||||||||||
2302 | * into account by the transformation such that only the inequalities | ||||||||||||
2303 | * are relevant. | ||||||||||||
2304 | * "context" is assumed not to be empty. | ||||||||||||
2305 | * | ||||||||||||
2306 | * "row" keeps track of the constraint index of a "bset" inequality in "tab". | ||||||||||||
2307 | * A value of -1 means that the inequality is obviously redundant and may | ||||||||||||
2308 | * not even appear in "tab". | ||||||||||||
2309 | * | ||||||||||||
2310 | * We first mark the inequalities of "bset" | ||||||||||||
2311 | * that are obviously redundant with respect to some inequality in "context". | ||||||||||||
2312 | * Then we remove those constraints from "context" that have become | ||||||||||||
2313 | * irrelevant for computing the gist of "bset". | ||||||||||||
2314 | * Note that this removal of constraints cannot be replaced by | ||||||||||||
2315 | * a factorization because factors in "bset" may still be connected | ||||||||||||
2316 | * to each other through constraints in "context". | ||||||||||||
2317 | * | ||||||||||||
2318 | * If there are any inequalities left, we construct a tableau for | ||||||||||||
2319 | * the context and then add the inequalities of "bset". | ||||||||||||
2320 | * Before adding these inequalities, we freeze all constraints such that | ||||||||||||
2321 | * they won't be considered redundant in terms of the constraints of "bset". | ||||||||||||
2322 | * Then we detect all redundant constraints (among the | ||||||||||||
2323 | * constraints that weren't frozen), first by checking for redundancy in the | ||||||||||||
2324 | * the tableau and then by checking if replacing a constraint by its negation | ||||||||||||
2325 | * would lead to an empty set. This last step is fairly expensive | ||||||||||||
2326 | * and could be optimized by more reuse of the tableau. | ||||||||||||
2327 | * Finally, we update bset according to the results. | ||||||||||||
2328 | */ | ||||||||||||
2329 | static __isl_give isl_basic_setisl_basic_map *uset_gist_full(__isl_take isl_basic_setisl_basic_map *bset, | ||||||||||||
2330 | __isl_take isl_mat *ineq, __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
2331 | { | ||||||||||||
2332 | int i, r; | ||||||||||||
2333 | int *row = NULL((void*)0); | ||||||||||||
2334 | isl_ctx *ctx; | ||||||||||||
2335 | isl_basic_setisl_basic_map *combined = NULL((void*)0); | ||||||||||||
2336 | struct isl_tab *tab = NULL((void*)0); | ||||||||||||
2337 | unsigned n_eq, context_ineq; | ||||||||||||
2338 | |||||||||||||
2339 | if (!bset || !ineq || !context) | ||||||||||||
2340 | goto error; | ||||||||||||
2341 | |||||||||||||
2342 | if (bset->n_ineq == 0 || isl_basic_set_plain_is_universe(context)) { | ||||||||||||
2343 | isl_basic_set_free(context); | ||||||||||||
2344 | isl_mat_free(ineq); | ||||||||||||
2345 | return bset; | ||||||||||||
2346 | } | ||||||||||||
2347 | |||||||||||||
2348 | ctx = isl_basic_set_get_ctx(context); | ||||||||||||
2349 | row = isl_calloc_array(ctx, int, bset->n_ineq)((int *)isl_calloc_or_die(ctx, bset->n_ineq, sizeof(int))); | ||||||||||||
2350 | if (!row) | ||||||||||||
2351 | goto error; | ||||||||||||
2352 | |||||||||||||
2353 | if (mark_shifted_constraints(ineq, context, row) < 0) | ||||||||||||
2354 | goto error; | ||||||||||||
2355 | if (all_neg(row, bset->n_ineq)) | ||||||||||||
2356 | return update_ineq_free(bset, ineq, context, row, NULL((void*)0)); | ||||||||||||
2357 | |||||||||||||
2358 | context = drop_irrelevant_constraints_marked(context, ineq, row); | ||||||||||||
2359 | if (!context) | ||||||||||||
2360 | goto error; | ||||||||||||
2361 | if (isl_basic_set_plain_is_universe(context)) | ||||||||||||
2362 | return update_ineq_free(bset, ineq, context, row, NULL((void*)0)); | ||||||||||||
2363 | |||||||||||||
2364 | n_eq = context->n_eq; | ||||||||||||
2365 | context_ineq = context->n_ineq; | ||||||||||||
2366 | combined = isl_basic_set_cow(isl_basic_set_copy(context)); | ||||||||||||
2367 | combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq); | ||||||||||||
2368 | tab = isl_tab_from_basic_set(combined, 0); | ||||||||||||
2369 | for (i = 0; i < context_ineq; ++i) | ||||||||||||
2370 | if (isl_tab_freeze_constraint(tab, n_eq + i) < 0) | ||||||||||||
2371 | goto error; | ||||||||||||
2372 | if (isl_tab_extend_cons(tab, bset->n_ineq) < 0) | ||||||||||||
2373 | goto error; | ||||||||||||
2374 | r = context_ineq; | ||||||||||||
2375 | for (i = 0; i < bset->n_ineq; ++i) { | ||||||||||||
2376 | if (row[i] < 0) | ||||||||||||
2377 | continue; | ||||||||||||
2378 | combined = isl_basic_set_add_ineq(combined, ineq->row[i]); | ||||||||||||
2379 | if (isl_tab_add_ineq(tab, ineq->row[i]) < 0) | ||||||||||||
2380 | goto error; | ||||||||||||
2381 | row[i] = r++; | ||||||||||||
2382 | } | ||||||||||||
2383 | if (isl_tab_detect_implicit_equalities(tab) < 0) | ||||||||||||
2384 | goto error; | ||||||||||||
2385 | if (isl_tab_detect_redundant(tab) < 0) | ||||||||||||
2386 | goto error; | ||||||||||||
2387 | for (i = bset->n_ineq - 1; i >= 0; --i) { | ||||||||||||
2388 | isl_basic_setisl_basic_map *test; | ||||||||||||
2389 | int is_empty; | ||||||||||||
2390 | |||||||||||||
2391 | if (row[i] < 0) | ||||||||||||
2392 | continue; | ||||||||||||
2393 | r = row[i]; | ||||||||||||
2394 | if (tab->con[n_eq + r].is_redundant) | ||||||||||||
2395 | continue; | ||||||||||||
2396 | test = isl_basic_set_dup(combined); | ||||||||||||
2397 | if (isl_inequality_negate(test, r) < 0) | ||||||||||||
2398 | test = isl_basic_set_free(test); | ||||||||||||
2399 | test = isl_basic_set_update_from_tab(test, tab); | ||||||||||||
2400 | is_empty = isl_basic_set_is_empty(test); | ||||||||||||
2401 | isl_basic_set_free(test); | ||||||||||||
2402 | if (is_empty < 0) | ||||||||||||
2403 | goto error; | ||||||||||||
2404 | if (is_empty) | ||||||||||||
2405 | tab->con[n_eq + r].is_redundant = 1; | ||||||||||||
2406 | } | ||||||||||||
2407 | bset = update_ineq_free(bset, ineq, context, row, tab); | ||||||||||||
2408 | if (bset) { | ||||||||||||
2409 | ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT)(((bset)->flags) |= ((1 << 2))); | ||||||||||||
2410 | ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT)(((bset)->flags) |= ((1 << 3))); | ||||||||||||
2411 | } | ||||||||||||
2412 | |||||||||||||
2413 | isl_basic_set_free(combined); | ||||||||||||
2414 | return bset; | ||||||||||||
2415 | error: | ||||||||||||
2416 | free(row); | ||||||||||||
2417 | isl_mat_free(ineq); | ||||||||||||
2418 | isl_tab_free(tab); | ||||||||||||
2419 | isl_basic_set_free(combined); | ||||||||||||
2420 | isl_basic_set_free(context); | ||||||||||||
2421 | isl_basic_set_free(bset); | ||||||||||||
2422 | return NULL((void*)0); | ||||||||||||
2423 | } | ||||||||||||
2424 | |||||||||||||
2425 | /* Extract the inequalities of "bset" as an isl_mat. | ||||||||||||
2426 | */ | ||||||||||||
2427 | static __isl_give isl_mat *extract_ineq(__isl_keep isl_basic_setisl_basic_map *bset) | ||||||||||||
2428 | { | ||||||||||||
2429 | unsigned total; | ||||||||||||
2430 | isl_ctx *ctx; | ||||||||||||
2431 | isl_mat *ineq; | ||||||||||||
2432 | |||||||||||||
2433 | if (!bset) | ||||||||||||
2434 | return NULL((void*)0); | ||||||||||||
2435 | |||||||||||||
2436 | ctx = isl_basic_set_get_ctx(bset); | ||||||||||||
2437 | total = isl_basic_set_total_dim(bset); | ||||||||||||
2438 | ineq = isl_mat_sub_alloc6(ctx, bset->ineq, 0, bset->n_ineq, | ||||||||||||
2439 | 0, 1 + total); | ||||||||||||
2440 | |||||||||||||
2441 | return ineq; | ||||||||||||
2442 | } | ||||||||||||
2443 | |||||||||||||
2444 | /* Remove all information from "bset" that is redundant in the context | ||||||||||||
2445 | * of "context", for the case where both "bset" and "context" are | ||||||||||||
2446 | * full-dimensional. | ||||||||||||
2447 | */ | ||||||||||||
2448 | static __isl_give isl_basic_setisl_basic_map *uset_gist_uncompressed( | ||||||||||||
2449 | __isl_take isl_basic_setisl_basic_map *bset, __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
2450 | { | ||||||||||||
2451 | isl_mat *ineq; | ||||||||||||
2452 | |||||||||||||
2453 | ineq = extract_ineq(bset); | ||||||||||||
2454 | return uset_gist_full(bset, ineq, context); | ||||||||||||
2455 | } | ||||||||||||
2456 | |||||||||||||
2457 | /* Remove all information from "bset" that is redundant in the context | ||||||||||||
2458 | * of "context", for the case where the combined equalities of | ||||||||||||
2459 | * "bset" and "context" allow for a compression that can be obtained | ||||||||||||
2460 | * by preapplication of "T". | ||||||||||||
2461 | * | ||||||||||||
2462 | * "bset" itself is not transformed by "T". Instead, the inequalities | ||||||||||||
2463 | * are extracted from "bset" and those are transformed by "T". | ||||||||||||
2464 | * uset_gist_full then determines which of the transformed inequalities | ||||||||||||
2465 | * are redundant with respect to the transformed "context" and removes | ||||||||||||
2466 | * the corresponding inequalities from "bset". | ||||||||||||
2467 | * | ||||||||||||
2468 | * After preapplying "T" to the inequalities, any common factor is | ||||||||||||
2469 | * removed from the coefficients. If this results in a tightening | ||||||||||||
2470 | * of the constant term, then the same tightening is applied to | ||||||||||||
2471 | * the corresponding untransformed inequality in "bset". | ||||||||||||
2472 | * That is, if after plugging in T, a constraint f(x) >= 0 is of the form | ||||||||||||
2473 | * | ||||||||||||
2474 | * g f'(x) + r >= 0 | ||||||||||||
2475 | * | ||||||||||||
2476 | * with 0 <= r < g, then it is equivalent to | ||||||||||||
2477 | * | ||||||||||||
2478 | * f'(x) >= 0 | ||||||||||||
2479 | * | ||||||||||||
2480 | * This means that f(x) >= 0 is equivalent to f(x) - r >= 0 in the affine | ||||||||||||
2481 | * subspace compressed by T since the latter would be transformed to | ||||||||||||
2482 | * | ||||||||||||
2483 | * g f'(x) >= 0 | ||||||||||||
2484 | */ | ||||||||||||
2485 | static __isl_give isl_basic_setisl_basic_map *uset_gist_compressed( | ||||||||||||
2486 | __isl_take isl_basic_setisl_basic_map *bset, __isl_take isl_basic_setisl_basic_map *context, | ||||||||||||
2487 | __isl_take isl_mat *T) | ||||||||||||
2488 | { | ||||||||||||
2489 | isl_ctx *ctx; | ||||||||||||
2490 | isl_mat *ineq; | ||||||||||||
2491 | int i, n_row, n_col; | ||||||||||||
2492 | isl_int rem; | ||||||||||||
2493 | |||||||||||||
2494 | ineq = extract_ineq(bset); | ||||||||||||
2495 | ineq = isl_mat_product(ineq, isl_mat_copy(T)); | ||||||||||||
2496 | context = isl_basic_set_preimage(context, T); | ||||||||||||
2497 | |||||||||||||
2498 | if (!ineq || !context) | ||||||||||||
2499 | goto error; | ||||||||||||
2500 | if (isl_basic_set_plain_is_empty(context)) { | ||||||||||||
2501 | isl_mat_free(ineq); | ||||||||||||
2502 | isl_basic_set_free(context); | ||||||||||||
2503 | return isl_basic_set_set_to_empty(bset); | ||||||||||||
2504 | } | ||||||||||||
2505 | |||||||||||||
2506 | ctx = isl_mat_get_ctx(ineq); | ||||||||||||
2507 | n_row = isl_mat_rows(ineq); | ||||||||||||
2508 | n_col = isl_mat_cols(ineq); | ||||||||||||
2509 | isl_int_init(rem)isl_sioimath_init((rem)); | ||||||||||||
2510 | for (i = 0; i < n_row; ++i) { | ||||||||||||
2511 | isl_seq_gcd(ineq->row[i] + 1, n_col - 1, &ctx->normalize_gcd); | ||||||||||||
2512 | if (isl_int_is_zero(ctx->normalize_gcd)(isl_sioimath_sgn(*(ctx->normalize_gcd)) == 0)) | ||||||||||||
2513 | continue; | ||||||||||||
2514 | if (isl_int_is_one(ctx->normalize_gcd)(isl_sioimath_cmp_si(*(ctx->normalize_gcd), 1) == 0)) | ||||||||||||
2515 | continue; | ||||||||||||
2516 | isl_seq_scale_down(ineq->row[i] + 1, ineq->row[i] + 1, | ||||||||||||
2517 | ctx->normalize_gcd, n_col - 1); | ||||||||||||
2518 | isl_int_fdiv_r(rem, ineq->row[i][0], ctx->normalize_gcd)isl_sioimath_fdiv_r((rem), *(ineq->row[i][0]), *(ctx->normalize_gcd )); | ||||||||||||
2519 | isl_int_fdiv_q(ineq->row[i][0],isl_sioimath_fdiv_q((ineq->row[i][0]), *(ineq->row[i][0 ]), *(ctx->normalize_gcd)) | ||||||||||||
2520 | ineq->row[i][0], ctx->normalize_gcd)isl_sioimath_fdiv_q((ineq->row[i][0]), *(ineq->row[i][0 ]), *(ctx->normalize_gcd)); | ||||||||||||
2521 | if (isl_int_is_zero(rem)(isl_sioimath_sgn(*(rem)) == 0)) | ||||||||||||
2522 | continue; | ||||||||||||
2523 | bset = isl_basic_set_cow(bset); | ||||||||||||
2524 | if (!bset) | ||||||||||||
2525 | break; | ||||||||||||
2526 | isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], rem)isl_sioimath_sub((bset->ineq[i][0]), *(bset->ineq[i][0] ), *(rem)); | ||||||||||||
2527 | } | ||||||||||||
2528 | isl_int_clear(rem)isl_sioimath_clear((rem)); | ||||||||||||
2529 | |||||||||||||
2530 | return uset_gist_full(bset, ineq, context); | ||||||||||||
2531 | error: | ||||||||||||
2532 | isl_mat_free(ineq); | ||||||||||||
2533 | isl_basic_set_free(context); | ||||||||||||
2534 | isl_basic_set_free(bset); | ||||||||||||
2535 | return NULL((void*)0); | ||||||||||||
2536 | } | ||||||||||||
2537 | |||||||||||||
2538 | /* Project "bset" onto the variables that are involved in "template". | ||||||||||||
2539 | */ | ||||||||||||
2540 | static __isl_give isl_basic_setisl_basic_map *project_onto_involved( | ||||||||||||
2541 | __isl_take isl_basic_setisl_basic_map *bset, __isl_keep isl_basic_setisl_basic_map *template) | ||||||||||||
2542 | { | ||||||||||||
2543 | int i, n; | ||||||||||||
2544 | |||||||||||||
2545 | if (!bset || !template) | ||||||||||||
2546 | return isl_basic_set_free(bset); | ||||||||||||
2547 | |||||||||||||
2548 | n = isl_basic_set_dim(template, isl_dim_set); | ||||||||||||
2549 | |||||||||||||
2550 | for (i = 0; i < n; ++i) { | ||||||||||||
2551 | isl_bool involved; | ||||||||||||
2552 | |||||||||||||
2553 | involved = isl_basic_set_involves_dims(template, | ||||||||||||
2554 | isl_dim_set, i, 1); | ||||||||||||
2555 | if (involved < 0) | ||||||||||||
2556 | return isl_basic_set_free(bset); | ||||||||||||
2557 | if (involved) | ||||||||||||
2558 | continue; | ||||||||||||
2559 | bset = isl_basic_set_eliminate_vars(bset, i, 1); | ||||||||||||
2560 | } | ||||||||||||
2561 | |||||||||||||
2562 | return bset; | ||||||||||||
2563 | } | ||||||||||||
2564 | |||||||||||||
2565 | /* Remove all information from bset that is redundant in the context | ||||||||||||
2566 | * of context. In particular, equalities that are linear combinations | ||||||||||||
2567 | * of those in context are removed. Then the inequalities that are | ||||||||||||
2568 | * redundant in the context of the equalities and inequalities of | ||||||||||||
2569 | * context are removed. | ||||||||||||
2570 | * | ||||||||||||
2571 | * First of all, we drop those constraints from "context" | ||||||||||||
2572 | * that are irrelevant for computing the gist of "bset". | ||||||||||||
2573 | * Alternatively, we could factorize the intersection of "context" and "bset". | ||||||||||||
2574 | * | ||||||||||||
2575 | * We first compute the intersection of the integer affine hulls | ||||||||||||
2576 | * of "bset" and "context", | ||||||||||||
2577 | * compute the gist inside this intersection and then reduce | ||||||||||||
2578 | * the constraints with respect to the equalities of the context | ||||||||||||
2579 | * that only involve variables already involved in the input. | ||||||||||||
2580 | * | ||||||||||||
2581 | * If two constraints are mutually redundant, then uset_gist_full | ||||||||||||
2582 | * will remove the second of those constraints. We therefore first | ||||||||||||
2583 | * sort the constraints so that constraints not involving existentially | ||||||||||||
2584 | * quantified variables are given precedence over those that do. | ||||||||||||
2585 | * We have to perform this sorting before the variable compression, | ||||||||||||
2586 | * because that may effect the order of the variables. | ||||||||||||
2587 | */ | ||||||||||||
2588 | static __isl_give isl_basic_setisl_basic_map *uset_gist(__isl_take isl_basic_setisl_basic_map *bset, | ||||||||||||
2589 | __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
2590 | { | ||||||||||||
2591 | isl_mat *eq; | ||||||||||||
2592 | isl_mat *T; | ||||||||||||
2593 | isl_basic_setisl_basic_map *aff; | ||||||||||||
2594 | isl_basic_setisl_basic_map *aff_context; | ||||||||||||
2595 | unsigned total; | ||||||||||||
2596 | |||||||||||||
2597 | if (!bset || !context) | ||||||||||||
2598 | goto error; | ||||||||||||
2599 | |||||||||||||
2600 | context = drop_irrelevant_constraints(context, bset); | ||||||||||||
2601 | |||||||||||||
2602 | bset = isl_basic_set_detect_equalities(bset); | ||||||||||||
2603 | aff = isl_basic_set_copy(bset); | ||||||||||||
2604 | aff = isl_basic_set_plain_affine_hull(aff); | ||||||||||||
2605 | context = isl_basic_set_detect_equalities(context); | ||||||||||||
2606 | aff_context = isl_basic_set_copy(context); | ||||||||||||
2607 | aff_context = isl_basic_set_plain_affine_hull(aff_context); | ||||||||||||
2608 | aff = isl_basic_set_intersect(aff, aff_context); | ||||||||||||
2609 | if (!aff) | ||||||||||||
2610 | goto error; | ||||||||||||
2611 | if (isl_basic_set_plain_is_empty(aff)) { | ||||||||||||
2612 | isl_basic_set_free(bset); | ||||||||||||
2613 | isl_basic_set_free(context); | ||||||||||||
2614 | return aff; | ||||||||||||
2615 | } | ||||||||||||
2616 | bset = isl_basic_set_sort_constraints(bset); | ||||||||||||
2617 | if (aff->n_eq == 0) { | ||||||||||||
2618 | isl_basic_set_free(aff); | ||||||||||||
2619 | return uset_gist_uncompressed(bset, context); | ||||||||||||
2620 | } | ||||||||||||
2621 | total = isl_basic_set_total_dim(bset); | ||||||||||||
2622 | eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total); | ||||||||||||
2623 | eq = isl_mat_cow(eq); | ||||||||||||
2624 | T = isl_mat_variable_compression(eq, NULL((void*)0)); | ||||||||||||
2625 | isl_basic_set_free(aff); | ||||||||||||
2626 | if (T && T->n_col == 0) { | ||||||||||||
2627 | isl_mat_free(T); | ||||||||||||
2628 | isl_basic_set_free(context); | ||||||||||||
2629 | return isl_basic_set_set_to_empty(bset); | ||||||||||||
2630 | } | ||||||||||||
2631 | |||||||||||||
2632 | aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context)); | ||||||||||||
2633 | aff_context = project_onto_involved(aff_context, bset); | ||||||||||||
2634 | |||||||||||||
2635 | bset = uset_gist_compressed(bset, context, T); | ||||||||||||
2636 | bset = isl_basic_set_reduce_using_equalities(bset, aff_context); | ||||||||||||
2637 | |||||||||||||
2638 | if (bset) { | ||||||||||||
2639 | ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT)(((bset)->flags) |= ((1 << 2))); | ||||||||||||
2640 | ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT)(((bset)->flags) |= ((1 << 3))); | ||||||||||||
2641 | } | ||||||||||||
2642 | |||||||||||||
2643 | return bset; | ||||||||||||
2644 | error: | ||||||||||||
2645 | isl_basic_set_free(bset); | ||||||||||||
2646 | isl_basic_set_free(context); | ||||||||||||
2647 | return NULL((void*)0); | ||||||||||||
2648 | } | ||||||||||||
2649 | |||||||||||||
2650 | /* Return the number of equality constraints in "bmap" that involve | ||||||||||||
2651 | * local variables. This function assumes that Gaussian elimination | ||||||||||||
2652 | * has been applied to the equality constraints. | ||||||||||||
2653 | */ | ||||||||||||
2654 | static int n_div_eq(__isl_keep isl_basic_map *bmap) | ||||||||||||
2655 | { | ||||||||||||
2656 | int i; | ||||||||||||
2657 | int total, n_div; | ||||||||||||
2658 | |||||||||||||
2659 | if (!bmap) | ||||||||||||
2660 | return -1; | ||||||||||||
2661 | |||||||||||||
2662 | if (bmap->n_eq == 0) | ||||||||||||
2663 | return 0; | ||||||||||||
2664 | |||||||||||||
2665 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
2666 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
2667 | total -= n_div; | ||||||||||||
2668 | |||||||||||||
2669 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
2670 | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, | ||||||||||||
2671 | n_div) == -1) | ||||||||||||
2672 | return i; | ||||||||||||
2673 | |||||||||||||
2674 | return bmap->n_eq; | ||||||||||||
2675 | } | ||||||||||||
2676 | |||||||||||||
2677 | /* Construct a basic map in "space" defined by the equality constraints in "eq". | ||||||||||||
2678 | * The constraints are assumed not to involve any local variables. | ||||||||||||
2679 | */ | ||||||||||||
2680 | static __isl_give isl_basic_map *basic_map_from_equalities( | ||||||||||||
2681 | __isl_take isl_space *space, __isl_take isl_mat *eq) | ||||||||||||
2682 | { | ||||||||||||
2683 | int i, k; | ||||||||||||
2684 | isl_basic_map *bmap = NULL((void*)0); | ||||||||||||
2685 | |||||||||||||
2686 | if (!space || !eq) | ||||||||||||
2687 | goto error; | ||||||||||||
2688 | |||||||||||||
2689 | if (1 + isl_space_dim(space, isl_dim_all) != eq->n_col) | ||||||||||||
2690 | isl_die(isl_space_get_ctx(space), isl_error_internal,do { isl_handle_error(isl_space_get_ctx(space), isl_error_internal , "unexpected number of columns", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 2691); goto error; } while (0) | ||||||||||||
2691 | "unexpected number of columns", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_internal , "unexpected number of columns", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 2691); goto error; } while (0); | ||||||||||||
2692 | |||||||||||||
2693 | bmap = isl_basic_map_alloc_space(isl_space_copy(space), | ||||||||||||
2694 | 0, eq->n_row, 0); | ||||||||||||
2695 | for (i = 0; i < eq->n_row; ++i) { | ||||||||||||
2696 | k = isl_basic_map_alloc_equality(bmap); | ||||||||||||
2697 | if (k < 0) | ||||||||||||
2698 | goto error; | ||||||||||||
2699 | isl_seq_cpy(bmap->eq[k], eq->row[i], eq->n_col); | ||||||||||||
2700 | } | ||||||||||||
2701 | |||||||||||||
2702 | isl_space_free(space); | ||||||||||||
2703 | isl_mat_free(eq); | ||||||||||||
2704 | return bmap; | ||||||||||||
2705 | error: | ||||||||||||
2706 | isl_space_free(space); | ||||||||||||
2707 | isl_mat_free(eq); | ||||||||||||
2708 | isl_basic_map_free(bmap); | ||||||||||||
2709 | return NULL((void*)0); | ||||||||||||
2710 | } | ||||||||||||
2711 | |||||||||||||
2712 | /* Construct and return a variable compression based on the equality | ||||||||||||
2713 | * constraints in "bmap1" and "bmap2" that do not involve the local variables. | ||||||||||||
2714 | * "n1" is the number of (initial) equality constraints in "bmap1" | ||||||||||||
2715 | * that do involve local variables. | ||||||||||||
2716 | * "n2" is the number of (initial) equality constraints in "bmap2" | ||||||||||||
2717 | * that do involve local variables. | ||||||||||||
2718 | * "total" is the total number of other variables. | ||||||||||||
2719 | * This function assumes that Gaussian elimination | ||||||||||||
2720 | * has been applied to the equality constraints in both "bmap1" and "bmap2" | ||||||||||||
2721 | * such that the equality constraints not involving local variables | ||||||||||||
2722 | * are those that start at "n1" or "n2". | ||||||||||||
2723 | * | ||||||||||||
2724 | * If either of "bmap1" and "bmap2" does not have such equality constraints, | ||||||||||||
2725 | * then simply compute the compression based on the equality constraints | ||||||||||||
2726 | * in the other basic map. | ||||||||||||
2727 | * Otherwise, combine the equality constraints from both into a new | ||||||||||||
2728 | * basic map such that Gaussian elimination can be applied to this combination | ||||||||||||
2729 | * and then construct a variable compression from the resulting | ||||||||||||
2730 | * equality constraints. | ||||||||||||
2731 | */ | ||||||||||||
2732 | static __isl_give isl_mat *combined_variable_compression( | ||||||||||||
2733 | __isl_keep isl_basic_map *bmap1, int n1, | ||||||||||||
2734 | __isl_keep isl_basic_map *bmap2, int n2, int total) | ||||||||||||
2735 | { | ||||||||||||
2736 | isl_ctx *ctx; | ||||||||||||
2737 | isl_mat *E1, *E2, *V; | ||||||||||||
2738 | isl_basic_map *bmap; | ||||||||||||
2739 | |||||||||||||
2740 | ctx = isl_basic_map_get_ctx(bmap1); | ||||||||||||
2741 | if (bmap1->n_eq == n1) { | ||||||||||||
2742 | E2 = isl_mat_sub_alloc6(ctx, bmap2->eq, | ||||||||||||
2743 | n2, bmap2->n_eq - n2, 0, 1 + total); | ||||||||||||
2744 | return isl_mat_variable_compression(E2, NULL((void*)0)); | ||||||||||||
2745 | } | ||||||||||||
2746 | if (bmap2->n_eq == n2) { | ||||||||||||
2747 | E1 = isl_mat_sub_alloc6(ctx, bmap1->eq, | ||||||||||||
2748 | n1, bmap1->n_eq - n1, 0, 1 + total); | ||||||||||||
2749 | return isl_mat_variable_compression(E1, NULL((void*)0)); | ||||||||||||
2750 | } | ||||||||||||
2751 | E1 = isl_mat_sub_alloc6(ctx, bmap1->eq, | ||||||||||||
2752 | n1, bmap1->n_eq - n1, 0, 1 + total); | ||||||||||||
2753 | E2 = isl_mat_sub_alloc6(ctx, bmap2->eq, | ||||||||||||
2754 | n2, bmap2->n_eq - n2, 0, 1 + total); | ||||||||||||
2755 | E1 = isl_mat_concat(E1, E2); | ||||||||||||
2756 | bmap = basic_map_from_equalities(isl_basic_map_get_space(bmap1), E1); | ||||||||||||
2757 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
2758 | if (!bmap) | ||||||||||||
2759 | return NULL((void*)0); | ||||||||||||
2760 | E1 = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total); | ||||||||||||
2761 | V = isl_mat_variable_compression(E1, NULL((void*)0)); | ||||||||||||
2762 | isl_basic_map_free(bmap); | ||||||||||||
2763 | |||||||||||||
2764 | return V; | ||||||||||||
2765 | } | ||||||||||||
2766 | |||||||||||||
2767 | /* Extract the stride constraints from "bmap", compressed | ||||||||||||
2768 | * with respect to both the stride constraints in "context" and | ||||||||||||
2769 | * the remaining equality constraints in both "bmap" and "context". | ||||||||||||
2770 | * "bmap_n_eq" is the number of (initial) stride constraints in "bmap". | ||||||||||||
2771 | * "context_n_eq" is the number of (initial) stride constraints in "context". | ||||||||||||
2772 | * | ||||||||||||
2773 | * Let x be all variables in "bmap" (and "context") other than the local | ||||||||||||
2774 | * variables. First compute a variable compression | ||||||||||||
2775 | * | ||||||||||||
2776 | * x = V x' | ||||||||||||
2777 | * | ||||||||||||
2778 | * based on the non-stride equality constraints in "bmap" and "context". | ||||||||||||
2779 | * Consider the stride constraints of "context", | ||||||||||||
2780 | * | ||||||||||||
2781 | * A(x) + B(y) = 0 | ||||||||||||
2782 | * | ||||||||||||
2783 | * with y the local variables and plug in the variable compression, | ||||||||||||
2784 | * resulting in | ||||||||||||
2785 | * | ||||||||||||
2786 | * A(V x') + B(y) = 0 | ||||||||||||
2787 | * | ||||||||||||
2788 | * Use these constraints to compute a parameter compression on x' | ||||||||||||
2789 | * | ||||||||||||
2790 | * x' = T x'' | ||||||||||||
2791 | * | ||||||||||||
2792 | * Now consider the stride constraints of "bmap" | ||||||||||||
2793 | * | ||||||||||||
2794 | * C(x) + D(y) = 0 | ||||||||||||
2795 | * | ||||||||||||
2796 | * and plug in x = V*T x''. | ||||||||||||
2797 | * That is, return A = [C*V*T D]. | ||||||||||||
2798 | */ | ||||||||||||
2799 | static __isl_give isl_mat *extract_compressed_stride_constraints( | ||||||||||||
2800 | __isl_keep isl_basic_map *bmap, int bmap_n_eq, | ||||||||||||
2801 | __isl_keep isl_basic_map *context, int context_n_eq) | ||||||||||||
2802 | { | ||||||||||||
2803 | int total, n_div; | ||||||||||||
2804 | isl_ctx *ctx; | ||||||||||||
2805 | isl_mat *A, *B, *T, *V; | ||||||||||||
2806 | |||||||||||||
2807 | total = isl_basic_map_dim(context, isl_dim_all); | ||||||||||||
2808 | n_div = isl_basic_map_dim(context, isl_dim_div); | ||||||||||||
2809 | total -= n_div; | ||||||||||||
2810 | |||||||||||||
2811 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
2812 | |||||||||||||
2813 | V = combined_variable_compression(bmap, bmap_n_eq, | ||||||||||||
2814 | context, context_n_eq, total); | ||||||||||||
2815 | |||||||||||||
2816 | A = isl_mat_sub_alloc6(ctx, context->eq, 0, context_n_eq, 0, 1 + total); | ||||||||||||
2817 | B = isl_mat_sub_alloc6(ctx, context->eq, | ||||||||||||
2818 | 0, context_n_eq, 1 + total, n_div); | ||||||||||||
2819 | A = isl_mat_product(A, isl_mat_copy(V)); | ||||||||||||
2820 | T = isl_mat_parameter_compression_ext(A, B); | ||||||||||||
2821 | T = isl_mat_product(V, T); | ||||||||||||
2822 | |||||||||||||
2823 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
2824 | T = isl_mat_diagonal(T, isl_mat_identity(ctx, n_div)); | ||||||||||||
2825 | |||||||||||||
2826 | A = isl_mat_sub_alloc6(ctx, bmap->eq, | ||||||||||||
2827 | 0, bmap_n_eq, 0, 1 + total + n_div); | ||||||||||||
2828 | A = isl_mat_product(A, T); | ||||||||||||
2829 | |||||||||||||
2830 | return A; | ||||||||||||
2831 | } | ||||||||||||
2832 | |||||||||||||
2833 | /* Remove the prime factors from *g that have an exponent that | ||||||||||||
2834 | * is strictly smaller than the exponent in "c". | ||||||||||||
2835 | * All exponents in *g are known to be smaller than or equal | ||||||||||||
2836 | * to those in "c". | ||||||||||||
2837 | * | ||||||||||||
2838 | * That is, if *g is equal to | ||||||||||||
2839 | * | ||||||||||||
2840 | * p_1^{e_1} p_2^{e_2} ... p_n^{e_n} | ||||||||||||
2841 | * | ||||||||||||
2842 | * and "c" is equal to | ||||||||||||
2843 | * | ||||||||||||
2844 | * p_1^{f_1} p_2^{f_2} ... p_n^{f_n} | ||||||||||||
2845 | * | ||||||||||||
2846 | * then update *g to | ||||||||||||
2847 | * | ||||||||||||
2848 | * p_1^{e_1 * (e_1 = f_1)} p_2^{e_2 * (e_2 = f_2)} ... | ||||||||||||
2849 | * p_n^{e_n * (e_n = f_n)} | ||||||||||||
2850 | * | ||||||||||||
2851 | * If e_i = f_i, then c / *g does not have any p_i factors and therefore | ||||||||||||
2852 | * neither does the gcd of *g and c / *g. | ||||||||||||
2853 | * If e_i < f_i, then the gcd of *g and c / *g has a positive | ||||||||||||
2854 | * power min(e_i, s_i) of p_i with s_i = f_i - e_i among its factors. | ||||||||||||
2855 | * Dividing *g by this gcd therefore strictly reduces the exponent | ||||||||||||
2856 | * of the prime factors that need to be removed, while leaving the | ||||||||||||
2857 | * other prime factors untouched. | ||||||||||||
2858 | * Repeating this process until gcd(*g, c / *g) = 1 therefore | ||||||||||||
2859 | * removes all undesired factors, without removing any others. | ||||||||||||
2860 | */ | ||||||||||||
2861 | static void remove_incomplete_powers(isl_int *g, isl_int c) | ||||||||||||
2862 | { | ||||||||||||
2863 | isl_int t; | ||||||||||||
2864 | |||||||||||||
2865 | isl_int_init(t)isl_sioimath_init((t)); | ||||||||||||
2866 | for (;;) { | ||||||||||||
2867 | isl_int_divexact(t, c, *g)isl_sioimath_tdiv_q((t), *(c), *(*g)); | ||||||||||||
2868 | isl_int_gcd(t, t, *g)isl_sioimath_gcd((t), *(t), *(*g)); | ||||||||||||
2869 | if (isl_int_is_one(t)(isl_sioimath_cmp_si(*(t), 1) == 0)) | ||||||||||||
2870 | break; | ||||||||||||
2871 | isl_int_divexact(*g, *g, t)isl_sioimath_tdiv_q((*g), *(*g), *(t)); | ||||||||||||
2872 | } | ||||||||||||
2873 | isl_int_clear(t)isl_sioimath_clear((t)); | ||||||||||||
2874 | } | ||||||||||||
2875 | |||||||||||||
2876 | /* Reduce the "n" stride constraints in "bmap" based on a copy "A" | ||||||||||||
2877 | * of the same stride constraints in a compressed space that exploits | ||||||||||||
2878 | * all equalities in the context and the other equalities in "bmap". | ||||||||||||
2879 | * | ||||||||||||
2880 | * If the stride constraints of "bmap" are of the form | ||||||||||||
2881 | * | ||||||||||||
2882 | * C(x) + D(y) = 0 | ||||||||||||
2883 | * | ||||||||||||
2884 | * then A is of the form | ||||||||||||
2885 | * | ||||||||||||
2886 | * B(x') + D(y) = 0 | ||||||||||||
2887 | * | ||||||||||||
2888 | * If any of these constraints involves only a single local variable y, | ||||||||||||
2889 | * then the constraint appears as | ||||||||||||
2890 | * | ||||||||||||
2891 | * f(x) + m y_i = 0 | ||||||||||||
2892 | * | ||||||||||||
2893 | * in "bmap" and as | ||||||||||||
2894 | * | ||||||||||||
2895 | * h(x') + m y_i = 0 | ||||||||||||
2896 | * | ||||||||||||
2897 | * in "A". | ||||||||||||
2898 | * | ||||||||||||
2899 | * Let g be the gcd of m and the coefficients of h. | ||||||||||||
2900 | * Then, in particular, g is a divisor of the coefficients of h and | ||||||||||||
2901 | * | ||||||||||||
2902 | * f(x) = h(x') | ||||||||||||
2903 | * | ||||||||||||
2904 | * is known to be a multiple of g. | ||||||||||||
2905 | * If some prime factor in m appears with the same exponent in g, | ||||||||||||
2906 | * then it can be removed from m because f(x) is already known | ||||||||||||
2907 | * to be a multiple of g and therefore in particular of this power | ||||||||||||
2908 | * of the prime factors. | ||||||||||||
2909 | * Prime factors that appear with a smaller exponent in g cannot | ||||||||||||
2910 | * be removed from m. | ||||||||||||
2911 | * Let g' be the divisor of g containing all prime factors that | ||||||||||||
2912 | * appear with the same exponent in m and g, then | ||||||||||||
2913 | * | ||||||||||||
2914 | * f(x) + m y_i = 0 | ||||||||||||
2915 | * | ||||||||||||
2916 | * can be replaced by | ||||||||||||
2917 | * | ||||||||||||
2918 | * f(x) + m/g' y_i' = 0 | ||||||||||||
2919 | * | ||||||||||||
2920 | * Note that (if g' != 1) this changes the explicit representation | ||||||||||||
2921 | * of y_i to that of y_i', so the integer division at position i | ||||||||||||
2922 | * is marked unknown and later recomputed by a call to | ||||||||||||
2923 | * isl_basic_map_gauss. | ||||||||||||
2924 | */ | ||||||||||||
2925 | static __isl_give isl_basic_map *reduce_stride_constraints( | ||||||||||||
2926 | __isl_take isl_basic_map *bmap, int n, __isl_keep isl_mat *A) | ||||||||||||
2927 | { | ||||||||||||
2928 | int i; | ||||||||||||
2929 | int total, n_div; | ||||||||||||
2930 | int any = 0; | ||||||||||||
2931 | isl_int gcd; | ||||||||||||
2932 | |||||||||||||
2933 | if (!bmap || !A) | ||||||||||||
2934 | return isl_basic_map_free(bmap); | ||||||||||||
2935 | |||||||||||||
2936 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
2937 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
2938 | total -= n_div; | ||||||||||||
2939 | |||||||||||||
2940 | isl_int_init(gcd)isl_sioimath_init((gcd)); | ||||||||||||
2941 | for (i = 0; i < n; ++i) { | ||||||||||||
2942 | int div; | ||||||||||||
2943 | |||||||||||||
2944 | div = isl_seq_first_non_zero(bmap->eq[i] + 1 + total, n_div); | ||||||||||||
2945 | if (div < 0) | ||||||||||||
2946 | isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_internal , "equality constraints modified unexpectedly", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 2948); goto error; } while (0) | ||||||||||||
2947 | "equality constraints modified unexpectedly",do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_internal , "equality constraints modified unexpectedly", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 2948); goto error; } while (0) | ||||||||||||
2948 | goto error)do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_internal , "equality constraints modified unexpectedly", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 2948); goto error; } while (0); | ||||||||||||
2949 | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total + div + 1, | ||||||||||||
2950 | n_div - div - 1) != -1) | ||||||||||||
2951 | continue; | ||||||||||||
2952 | if (isl_mat_row_gcd(A, i, &gcd) < 0) | ||||||||||||
2953 | goto error; | ||||||||||||
2954 | if (isl_int_is_one(gcd)(isl_sioimath_cmp_si(*(gcd), 1) == 0)) | ||||||||||||
2955 | continue; | ||||||||||||
2956 | remove_incomplete_powers(&gcd, bmap->eq[i][1 + total + div]); | ||||||||||||
2957 | if (isl_int_is_one(gcd)(isl_sioimath_cmp_si(*(gcd), 1) == 0)) | ||||||||||||
2958 | continue; | ||||||||||||
2959 | isl_int_divexact(bmap->eq[i][1 + total + div],isl_sioimath_tdiv_q((bmap->eq[i][1 + total + div]), *(bmap ->eq[i][1 + total + div]), *(gcd)) | ||||||||||||
2960 | bmap->eq[i][1 + total + div], gcd)isl_sioimath_tdiv_q((bmap->eq[i][1 + total + div]), *(bmap ->eq[i][1 + total + div]), *(gcd)); | ||||||||||||
2961 | bmap = isl_basic_map_mark_div_unknown(bmap, div); | ||||||||||||
2962 | if (!bmap) | ||||||||||||
2963 | goto error; | ||||||||||||
2964 | any = 1; | ||||||||||||
2965 | } | ||||||||||||
2966 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); | ||||||||||||
2967 | |||||||||||||
2968 | if (any) | ||||||||||||
2969 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
2970 | |||||||||||||
2971 | return bmap; | ||||||||||||
2972 | error: | ||||||||||||
2973 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); | ||||||||||||
2974 | isl_basic_map_free(bmap); | ||||||||||||
2975 | return NULL((void*)0); | ||||||||||||
2976 | } | ||||||||||||
2977 | |||||||||||||
2978 | /* Simplify the stride constraints in "bmap" based on | ||||||||||||
2979 | * the remaining equality constraints in "bmap" and all equality | ||||||||||||
2980 | * constraints in "context". | ||||||||||||
2981 | * Only do this if both "bmap" and "context" have stride constraints. | ||||||||||||
2982 | * | ||||||||||||
2983 | * First extract a copy of the stride constraints in "bmap" in a compressed | ||||||||||||
2984 | * space exploiting all the other equality constraints and then | ||||||||||||
2985 | * use this compressed copy to simplify the original stride constraints. | ||||||||||||
2986 | */ | ||||||||||||
2987 | static __isl_give isl_basic_map *gist_strides(__isl_take isl_basic_map *bmap, | ||||||||||||
2988 | __isl_keep isl_basic_map *context) | ||||||||||||
2989 | { | ||||||||||||
2990 | int bmap_n_eq, context_n_eq; | ||||||||||||
2991 | isl_mat *A; | ||||||||||||
2992 | |||||||||||||
2993 | if (!bmap || !context) | ||||||||||||
2994 | return isl_basic_map_free(bmap); | ||||||||||||
2995 | |||||||||||||
2996 | bmap_n_eq = n_div_eq(bmap); | ||||||||||||
2997 | context_n_eq = n_div_eq(context); | ||||||||||||
2998 | |||||||||||||
2999 | if (bmap_n_eq < 0 || context_n_eq < 0) | ||||||||||||
3000 | return isl_basic_map_free(bmap); | ||||||||||||
3001 | if (bmap_n_eq == 0 || context_n_eq == 0) | ||||||||||||
3002 | return bmap; | ||||||||||||
3003 | |||||||||||||
3004 | A = extract_compressed_stride_constraints(bmap, bmap_n_eq, | ||||||||||||
3005 | context, context_n_eq); | ||||||||||||
3006 | bmap = reduce_stride_constraints(bmap, bmap_n_eq, A); | ||||||||||||
3007 | |||||||||||||
3008 | isl_mat_free(A); | ||||||||||||
3009 | |||||||||||||
3010 | return bmap; | ||||||||||||
3011 | } | ||||||||||||
3012 | |||||||||||||
3013 | /* Return a basic map that has the same intersection with "context" as "bmap" | ||||||||||||
3014 | * and that is as "simple" as possible. | ||||||||||||
3015 | * | ||||||||||||
3016 | * The core computation is performed on the pure constraints. | ||||||||||||
3017 | * When we add back the meaning of the integer divisions, we need | ||||||||||||
3018 | * to (re)introduce the div constraints. If we happen to have | ||||||||||||
3019 | * discovered that some of these integer divisions are equal to | ||||||||||||
3020 | * some affine combination of other variables, then these div | ||||||||||||
3021 | * constraints may end up getting simplified in terms of the equalities, | ||||||||||||
3022 | * resulting in extra inequalities on the other variables that | ||||||||||||
3023 | * may have been removed already or that may not even have been | ||||||||||||
3024 | * part of the input. We try and remove those constraints of | ||||||||||||
3025 | * this form that are most obviously redundant with respect to | ||||||||||||
3026 | * the context. We also remove those div constraints that are | ||||||||||||
3027 | * redundant with respect to the other constraints in the result. | ||||||||||||
3028 | * | ||||||||||||
3029 | * The stride constraints among the equality constraints in "bmap" are | ||||||||||||
3030 | * also simplified with respecting to the other equality constraints | ||||||||||||
3031 | * in "bmap" and with respect to all equality constraints in "context". | ||||||||||||
3032 | */ | ||||||||||||
3033 | __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap, | ||||||||||||
3034 | __isl_take isl_basic_map *context) | ||||||||||||
3035 | { | ||||||||||||
3036 | isl_basic_setisl_basic_map *bset, *eq; | ||||||||||||
3037 | isl_basic_map *eq_bmap; | ||||||||||||
3038 | unsigned total, n_div, extra, n_eq, n_ineq; | ||||||||||||
3039 | |||||||||||||
3040 | if (!bmap || !context) | ||||||||||||
3041 | goto error; | ||||||||||||
3042 | |||||||||||||
3043 | if (isl_basic_map_plain_is_universe(bmap)) { | ||||||||||||
3044 | isl_basic_map_free(context); | ||||||||||||
3045 | return bmap; | ||||||||||||
3046 | } | ||||||||||||
3047 | if (isl_basic_map_plain_is_empty(context)) { | ||||||||||||
3048 | isl_space *space = isl_basic_map_get_space(bmap); | ||||||||||||
3049 | isl_basic_map_free(bmap); | ||||||||||||
3050 | isl_basic_map_free(context); | ||||||||||||
3051 | return isl_basic_map_universe(space); | ||||||||||||
3052 | } | ||||||||||||
3053 | if (isl_basic_map_plain_is_empty(bmap)) { | ||||||||||||
3054 | isl_basic_map_free(context); | ||||||||||||
3055 | return bmap; | ||||||||||||
3056 | } | ||||||||||||
3057 | |||||||||||||
3058 | bmap = isl_basic_map_remove_redundancies(bmap); | ||||||||||||
3059 | context = isl_basic_map_remove_redundancies(context); | ||||||||||||
3060 | context = isl_basic_map_align_divs(context, bmap); | ||||||||||||
3061 | if (!context) | ||||||||||||
3062 | goto error; | ||||||||||||
3063 | |||||||||||||
3064 | n_div = isl_basic_map_dim(context, isl_dim_div); | ||||||||||||
3065 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
3066 | extra = n_div - isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
3067 | |||||||||||||
3068 | bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); | ||||||||||||
3069 | bset = isl_basic_set_add_dims(bset, isl_dim_set, extra); | ||||||||||||
3070 | bset = uset_gist(bset, | ||||||||||||
3071 | isl_basic_map_underlying_set(isl_basic_map_copy(context))); | ||||||||||||
3072 | bset = isl_basic_set_project_out(bset, isl_dim_set, total, extra); | ||||||||||||
3073 | |||||||||||||
3074 | if (!bset || bset->n_eq == 0 || n_div == 0 || | ||||||||||||
3075 | isl_basic_set_plain_is_empty(bset)) { | ||||||||||||
3076 | isl_basic_map_free(context); | ||||||||||||
3077 | return isl_basic_map_overlying_set(bset, bmap); | ||||||||||||
3078 | } | ||||||||||||
3079 | |||||||||||||
3080 | n_eq = bset->n_eq; | ||||||||||||
3081 | n_ineq = bset->n_ineq; | ||||||||||||
3082 | eq = isl_basic_set_copy(bset); | ||||||||||||
3083 | eq = isl_basic_set_cow(eq); | ||||||||||||
3084 | if (isl_basic_set_free_inequality(eq, n_ineq) < 0) | ||||||||||||
3085 | eq = isl_basic_set_free(eq); | ||||||||||||
3086 | if (isl_basic_set_free_equality(bset, n_eq) < 0) | ||||||||||||
3087 | bset = isl_basic_set_free(bset); | ||||||||||||
3088 | |||||||||||||
3089 | eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap)); | ||||||||||||
3090 | eq_bmap = gist_strides(eq_bmap, context); | ||||||||||||
3091 | eq_bmap = isl_basic_map_remove_shifted_constraints(eq_bmap, context); | ||||||||||||
3092 | bmap = isl_basic_map_overlying_set(bset, bmap); | ||||||||||||
3093 | bmap = isl_basic_map_intersect(bmap, eq_bmap); | ||||||||||||
3094 | bmap = isl_basic_map_remove_redundancies(bmap); | ||||||||||||
3095 | |||||||||||||
3096 | return bmap; | ||||||||||||
3097 | error: | ||||||||||||
3098 | isl_basic_map_free(bmap); | ||||||||||||
3099 | isl_basic_map_free(context); | ||||||||||||
3100 | return NULL((void*)0); | ||||||||||||
3101 | } | ||||||||||||
3102 | |||||||||||||
3103 | /* | ||||||||||||
3104 | * Assumes context has no implicit divs. | ||||||||||||
3105 | */ | ||||||||||||
3106 | __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map, | ||||||||||||
3107 | __isl_take isl_basic_map *context) | ||||||||||||
3108 | { | ||||||||||||
3109 | int i; | ||||||||||||
3110 | |||||||||||||
3111 | if (!map || !context) | ||||||||||||
3112 | goto error; | ||||||||||||
3113 | |||||||||||||
3114 | if (isl_basic_map_plain_is_empty(context)) { | ||||||||||||
3115 | isl_space *space = isl_map_get_space(map); | ||||||||||||
3116 | isl_map_free(map); | ||||||||||||
3117 | isl_basic_map_free(context); | ||||||||||||
3118 | return isl_map_universe(space); | ||||||||||||
3119 | } | ||||||||||||
3120 | |||||||||||||
3121 | context = isl_basic_map_remove_redundancies(context); | ||||||||||||
3122 | map = isl_map_cow(map); | ||||||||||||
3123 | if (!map || !context) | ||||||||||||
3124 | goto error; | ||||||||||||
3125 | isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error)do { if (isl_space_is_equal(map->dim, context->dim)) break ; do { isl_handle_error(map->ctx, isl_error_unknown, "Assertion \"" "isl_space_is_equal(map->dim, context->dim)" "\" failed" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3125); goto error; } while (0); } while (0); | ||||||||||||
3126 | map = isl_map_compute_divs(map); | ||||||||||||
3127 | if (!map) | ||||||||||||
3128 | goto error; | ||||||||||||
3129 | for (i = map->n - 1; i >= 0; --i) { | ||||||||||||
3130 | map->p[i] = isl_basic_map_gist(map->p[i], | ||||||||||||
3131 | isl_basic_map_copy(context)); | ||||||||||||
3132 | if (!map->p[i]) | ||||||||||||
3133 | goto error; | ||||||||||||
3134 | if (isl_basic_map_plain_is_empty(map->p[i])) { | ||||||||||||
3135 | isl_basic_map_free(map->p[i]); | ||||||||||||
3136 | if (i != map->n - 1) | ||||||||||||
3137 | map->p[i] = map->p[map->n - 1]; | ||||||||||||
3138 | map->n--; | ||||||||||||
3139 | } | ||||||||||||
3140 | } | ||||||||||||
3141 | isl_basic_map_free(context); | ||||||||||||
3142 | ISL_F_CLR(map, ISL_MAP_NORMALIZED)(((map)->flags) &= ~((1 << 1))); | ||||||||||||
3143 | return map; | ||||||||||||
3144 | error: | ||||||||||||
3145 | isl_map_free(map); | ||||||||||||
3146 | isl_basic_map_free(context); | ||||||||||||
3147 | return NULL((void*)0); | ||||||||||||
3148 | } | ||||||||||||
3149 | |||||||||||||
3150 | /* Drop all inequalities from "bmap" that also appear in "context". | ||||||||||||
3151 | * "context" is assumed to have only known local variables and | ||||||||||||
3152 | * the initial local variables of "bmap" are assumed to be the same | ||||||||||||
3153 | * as those of "context". | ||||||||||||
3154 | * The constraints of both "bmap" and "context" are assumed | ||||||||||||
3155 | * to have been sorted using isl_basic_map_sort_constraints. | ||||||||||||
3156 | * | ||||||||||||
3157 | * Run through the inequality constraints of "bmap" and "context" | ||||||||||||
3158 | * in sorted order. | ||||||||||||
3159 | * If a constraint of "bmap" involves variables not in "context", | ||||||||||||
3160 | * then it cannot appear in "context". | ||||||||||||
3161 | * If a matching constraint is found, it is removed from "bmap". | ||||||||||||
3162 | */ | ||||||||||||
3163 | static __isl_give isl_basic_map *drop_inequalities( | ||||||||||||
3164 | __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context) | ||||||||||||
3165 | { | ||||||||||||
3166 | int i1, i2; | ||||||||||||
3167 | unsigned total, extra; | ||||||||||||
3168 | |||||||||||||
3169 | if (!bmap || !context) | ||||||||||||
3170 | return isl_basic_map_free(bmap); | ||||||||||||
3171 | |||||||||||||
3172 | total = isl_basic_map_total_dim(context); | ||||||||||||
3173 | extra = isl_basic_map_total_dim(bmap) - total; | ||||||||||||
3174 | |||||||||||||
3175 | i1 = bmap->n_ineq - 1; | ||||||||||||
3176 | i2 = context->n_ineq - 1; | ||||||||||||
3177 | while (bmap && i1 >= 0 && i2 >= 0) { | ||||||||||||
3178 | int cmp; | ||||||||||||
3179 | |||||||||||||
3180 | if (isl_seq_first_non_zero(bmap->ineq[i1] + 1 + total, | ||||||||||||
3181 | extra) != -1) { | ||||||||||||
3182 | --i1; | ||||||||||||
3183 | continue; | ||||||||||||
3184 | } | ||||||||||||
3185 | cmp = isl_basic_map_constraint_cmp(context, bmap->ineq[i1], | ||||||||||||
3186 | context->ineq[i2]); | ||||||||||||
3187 | if (cmp < 0) { | ||||||||||||
3188 | --i2; | ||||||||||||
3189 | continue; | ||||||||||||
3190 | } | ||||||||||||
3191 | if (cmp > 0) { | ||||||||||||
3192 | --i1; | ||||||||||||
3193 | continue; | ||||||||||||
3194 | } | ||||||||||||
3195 | if (isl_int_eq(bmap->ineq[i1][0], context->ineq[i2][0])(isl_sioimath_cmp(*(bmap->ineq[i1][0]), *(context->ineq [i2][0])) == 0)) { | ||||||||||||
3196 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
3197 | if (isl_basic_map_drop_inequality(bmap, i1) < 0) | ||||||||||||
3198 | bmap = isl_basic_map_free(bmap); | ||||||||||||
3199 | } | ||||||||||||
3200 | --i1; | ||||||||||||
3201 | --i2; | ||||||||||||
3202 | } | ||||||||||||
3203 | |||||||||||||
3204 | return bmap; | ||||||||||||
3205 | } | ||||||||||||
3206 | |||||||||||||
3207 | /* Drop all equalities from "bmap" that also appear in "context". | ||||||||||||
3208 | * "context" is assumed to have only known local variables and | ||||||||||||
3209 | * the initial local variables of "bmap" are assumed to be the same | ||||||||||||
3210 | * as those of "context". | ||||||||||||
3211 | * | ||||||||||||
3212 | * Run through the equality constraints of "bmap" and "context" | ||||||||||||
3213 | * in sorted order. | ||||||||||||
3214 | * If a constraint of "bmap" involves variables not in "context", | ||||||||||||
3215 | * then it cannot appear in "context". | ||||||||||||
3216 | * If a matching constraint is found, it is removed from "bmap". | ||||||||||||
3217 | */ | ||||||||||||
3218 | static __isl_give isl_basic_map *drop_equalities( | ||||||||||||
3219 | __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context) | ||||||||||||
3220 | { | ||||||||||||
3221 | int i1, i2; | ||||||||||||
3222 | unsigned total, extra; | ||||||||||||
3223 | |||||||||||||
3224 | if (!bmap || !context) | ||||||||||||
3225 | return isl_basic_map_free(bmap); | ||||||||||||
3226 | |||||||||||||
3227 | total = isl_basic_map_total_dim(context); | ||||||||||||
3228 | extra = isl_basic_map_total_dim(bmap) - total; | ||||||||||||
3229 | |||||||||||||
3230 | i1 = bmap->n_eq - 1; | ||||||||||||
3231 | i2 = context->n_eq - 1; | ||||||||||||
3232 | |||||||||||||
3233 | while (bmap && i1 >= 0 && i2 >= 0) { | ||||||||||||
3234 | int last1, last2; | ||||||||||||
3235 | |||||||||||||
3236 | if (isl_seq_first_non_zero(bmap->eq[i1] + 1 + total, | ||||||||||||
3237 | extra) != -1) | ||||||||||||
3238 | break; | ||||||||||||
3239 | last1 = isl_seq_last_non_zero(bmap->eq[i1] + 1, total); | ||||||||||||
3240 | last2 = isl_seq_last_non_zero(context->eq[i2] + 1, total); | ||||||||||||
3241 | if (last1 > last2) { | ||||||||||||
3242 | --i2; | ||||||||||||
3243 | continue; | ||||||||||||
3244 | } | ||||||||||||
3245 | if (last1 < last2) { | ||||||||||||
3246 | --i1; | ||||||||||||
3247 | continue; | ||||||||||||
3248 | } | ||||||||||||
3249 | if (isl_seq_eq(bmap->eq[i1], context->eq[i2], 1 + total)) { | ||||||||||||
3250 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
3251 | if (isl_basic_map_drop_equality(bmap, i1) < 0) | ||||||||||||
3252 | bmap = isl_basic_map_free(bmap); | ||||||||||||
3253 | } | ||||||||||||
3254 | --i1; | ||||||||||||
3255 | --i2; | ||||||||||||
3256 | } | ||||||||||||
3257 | |||||||||||||
3258 | return bmap; | ||||||||||||
3259 | } | ||||||||||||
3260 | |||||||||||||
3261 | /* Remove the constraints in "context" from "bmap". | ||||||||||||
3262 | * "context" is assumed to have explicit representations | ||||||||||||
3263 | * for all local variables. | ||||||||||||
3264 | * | ||||||||||||
3265 | * First align the divs of "bmap" to those of "context" and | ||||||||||||
3266 | * sort the constraints. Then drop all constraints from "bmap" | ||||||||||||
3267 | * that appear in "context". | ||||||||||||
3268 | */ | ||||||||||||
3269 | __isl_give isl_basic_map *isl_basic_map_plain_gist( | ||||||||||||
3270 | __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context) | ||||||||||||
3271 | { | ||||||||||||
3272 | isl_bool done, known; | ||||||||||||
3273 | |||||||||||||
3274 | done = isl_basic_map_plain_is_universe(context); | ||||||||||||
3275 | if (done == isl_bool_false) | ||||||||||||
3276 | done = isl_basic_map_plain_is_universe(bmap); | ||||||||||||
3277 | if (done == isl_bool_false) | ||||||||||||
3278 | done = isl_basic_map_plain_is_empty(context); | ||||||||||||
3279 | if (done == isl_bool_false) | ||||||||||||
3280 | done = isl_basic_map_plain_is_empty(bmap); | ||||||||||||
3281 | if (done < 0) | ||||||||||||
3282 | goto error; | ||||||||||||
3283 | if (done) { | ||||||||||||
3284 | isl_basic_map_free(context); | ||||||||||||
3285 | return bmap; | ||||||||||||
3286 | } | ||||||||||||
3287 | known = isl_basic_map_divs_known(context); | ||||||||||||
3288 | if (known < 0) | ||||||||||||
3289 | goto error; | ||||||||||||
3290 | if (!known) | ||||||||||||
3291 | isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_invalid , "context has unknown divs", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3292); goto error; } while (0) | ||||||||||||
3292 | "context has unknown divs", goto error)do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_invalid , "context has unknown divs", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3292); goto error; } while (0); | ||||||||||||
3293 | |||||||||||||
3294 | bmap = isl_basic_map_align_divs(bmap, context); | ||||||||||||
3295 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
3296 | bmap = isl_basic_map_sort_constraints(bmap); | ||||||||||||
3297 | context = isl_basic_map_sort_constraints(context); | ||||||||||||
3298 | |||||||||||||
3299 | bmap = drop_inequalities(bmap, context); | ||||||||||||
3300 | bmap = drop_equalities(bmap, context); | ||||||||||||
3301 | |||||||||||||
3302 | isl_basic_map_free(context); | ||||||||||||
3303 | bmap = isl_basic_map_finalize(bmap); | ||||||||||||
3304 | return bmap; | ||||||||||||
3305 | error: | ||||||||||||
3306 | isl_basic_map_free(bmap); | ||||||||||||
3307 | isl_basic_map_free(context); | ||||||||||||
3308 | return NULL((void*)0); | ||||||||||||
3309 | } | ||||||||||||
3310 | |||||||||||||
3311 | /* Replace "map" by the disjunct at position "pos" and free "context". | ||||||||||||
3312 | */ | ||||||||||||
3313 | static __isl_give isl_map *replace_by_disjunct(__isl_take isl_map *map, | ||||||||||||
3314 | int pos, __isl_take isl_basic_map *context) | ||||||||||||
3315 | { | ||||||||||||
3316 | isl_basic_map *bmap; | ||||||||||||
3317 | |||||||||||||
3318 | bmap = isl_basic_map_copy(map->p[pos]); | ||||||||||||
3319 | isl_map_free(map); | ||||||||||||
3320 | isl_basic_map_free(context); | ||||||||||||
3321 | return isl_map_from_basic_map(bmap); | ||||||||||||
3322 | } | ||||||||||||
3323 | |||||||||||||
3324 | /* Remove the constraints in "context" from "map". | ||||||||||||
3325 | * If any of the disjuncts in the result turns out to be the universe, | ||||||||||||
3326 | * then return this universe. | ||||||||||||
3327 | * "context" is assumed to have explicit representations | ||||||||||||
3328 | * for all local variables. | ||||||||||||
3329 | */ | ||||||||||||
3330 | __isl_give isl_map *isl_map_plain_gist_basic_map(__isl_take isl_map *map, | ||||||||||||
3331 | __isl_take isl_basic_map *context) | ||||||||||||
3332 | { | ||||||||||||
3333 | int i; | ||||||||||||
3334 | isl_bool univ, known; | ||||||||||||
3335 | |||||||||||||
3336 | univ = isl_basic_map_plain_is_universe(context); | ||||||||||||
3337 | if (univ < 0) | ||||||||||||
3338 | goto error; | ||||||||||||
3339 | if (univ) { | ||||||||||||
3340 | isl_basic_map_free(context); | ||||||||||||
3341 | return map; | ||||||||||||
3342 | } | ||||||||||||
3343 | known = isl_basic_map_divs_known(context); | ||||||||||||
3344 | if (known < 0) | ||||||||||||
3345 | goto error; | ||||||||||||
3346 | if (!known) | ||||||||||||
3347 | isl_die(isl_map_get_ctx(map), isl_error_invalid,do { isl_handle_error(isl_map_get_ctx(map), isl_error_invalid , "context has unknown divs", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3348); goto error; } while (0) | ||||||||||||
3348 | "context has unknown divs", goto error)do { isl_handle_error(isl_map_get_ctx(map), isl_error_invalid , "context has unknown divs", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3348); goto error; } while (0); | ||||||||||||
3349 | |||||||||||||
3350 | map = isl_map_cow(map); | ||||||||||||
3351 | if (!map) | ||||||||||||
3352 | goto error; | ||||||||||||
3353 | for (i = 0; i < map->n; ++i) { | ||||||||||||
3354 | map->p[i] = isl_basic_map_plain_gist(map->p[i], | ||||||||||||
3355 | isl_basic_map_copy(context)); | ||||||||||||
3356 | univ = isl_basic_map_plain_is_universe(map->p[i]); | ||||||||||||
3357 | if (univ < 0) | ||||||||||||
3358 | goto error; | ||||||||||||
3359 | if (univ && map->n > 1) | ||||||||||||
3360 | return replace_by_disjunct(map, i, context); | ||||||||||||
3361 | } | ||||||||||||
3362 | |||||||||||||
3363 | isl_basic_map_free(context); | ||||||||||||
3364 | ISL_F_CLR(map, ISL_MAP_NORMALIZED)(((map)->flags) &= ~((1 << 1))); | ||||||||||||
3365 | if (map->n > 1) | ||||||||||||
3366 | ISL_F_CLR(map, ISL_MAP_DISJOINT)(((map)->flags) &= ~((1 << 0))); | ||||||||||||
3367 | return map; | ||||||||||||
3368 | error: | ||||||||||||
3369 | isl_map_free(map); | ||||||||||||
3370 | isl_basic_map_free(context); | ||||||||||||
3371 | return NULL((void*)0); | ||||||||||||
3372 | } | ||||||||||||
3373 | |||||||||||||
3374 | /* Remove the constraints in "context" from "set". | ||||||||||||
3375 | * If any of the disjuncts in the result turns out to be the universe, | ||||||||||||
3376 | * then return this universe. | ||||||||||||
3377 | * "context" is assumed to have explicit representations | ||||||||||||
3378 | * for all local variables. | ||||||||||||
3379 | */ | ||||||||||||
3380 | __isl_give isl_setisl_map *isl_set_plain_gist_basic_set(__isl_take isl_setisl_map *set, | ||||||||||||
3381 | __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
3382 | { | ||||||||||||
3383 | return set_from_map(isl_map_plain_gist_basic_map(set_to_map(set), | ||||||||||||
3384 | bset_to_bmap(context))); | ||||||||||||
3385 | } | ||||||||||||
3386 | |||||||||||||
3387 | /* Remove the constraints in "context" from "map". | ||||||||||||
3388 | * If any of the disjuncts in the result turns out to be the universe, | ||||||||||||
3389 | * then return this universe. | ||||||||||||
3390 | * "context" is assumed to consist of a single disjunct and | ||||||||||||
3391 | * to have explicit representations for all local variables. | ||||||||||||
3392 | */ | ||||||||||||
3393 | __isl_give isl_map *isl_map_plain_gist(__isl_take isl_map *map, | ||||||||||||
3394 | __isl_take isl_map *context) | ||||||||||||
3395 | { | ||||||||||||
3396 | isl_basic_map *hull; | ||||||||||||
3397 | |||||||||||||
3398 | hull = isl_map_unshifted_simple_hull(context); | ||||||||||||
3399 | return isl_map_plain_gist_basic_map(map, hull); | ||||||||||||
3400 | } | ||||||||||||
3401 | |||||||||||||
3402 | /* Replace "map" by a universe map in the same space and free "drop". | ||||||||||||
3403 | */ | ||||||||||||
3404 | static __isl_give isl_map *replace_by_universe(__isl_take isl_map *map, | ||||||||||||
3405 | __isl_take isl_map *drop) | ||||||||||||
3406 | { | ||||||||||||
3407 | isl_map *res; | ||||||||||||
3408 | |||||||||||||
3409 | res = isl_map_universe(isl_map_get_space(map)); | ||||||||||||
3410 | isl_map_free(map); | ||||||||||||
3411 | isl_map_free(drop); | ||||||||||||
3412 | return res; | ||||||||||||
3413 | } | ||||||||||||
3414 | |||||||||||||
3415 | /* Return a map that has the same intersection with "context" as "map" | ||||||||||||
3416 | * and that is as "simple" as possible. | ||||||||||||
3417 | * | ||||||||||||
3418 | * If "map" is already the universe, then we cannot make it any simpler. | ||||||||||||
3419 | * Similarly, if "context" is the universe, then we cannot exploit it | ||||||||||||
3420 | * to simplify "map" | ||||||||||||
3421 | * If "map" and "context" are identical to each other, then we can | ||||||||||||
3422 | * return the corresponding universe. | ||||||||||||
3423 | * | ||||||||||||
3424 | * If either "map" or "context" consists of multiple disjuncts, | ||||||||||||
3425 | * then check if "context" happens to be a subset of "map", | ||||||||||||
3426 | * in which case all constraints can be removed. | ||||||||||||
3427 | * In case of multiple disjuncts, the standard procedure | ||||||||||||
3428 | * may not be able to detect that all constraints can be removed. | ||||||||||||
3429 | * | ||||||||||||
3430 | * If none of these cases apply, we have to work a bit harder. | ||||||||||||
3431 | * During this computation, we make use of a single disjunct context, | ||||||||||||
3432 | * so if the original context consists of more than one disjunct | ||||||||||||
3433 | * then we need to approximate the context by a single disjunct set. | ||||||||||||
3434 | * Simply taking the simple hull may drop constraints that are | ||||||||||||
3435 | * only implicitly available in each disjunct. We therefore also | ||||||||||||
3436 | * look for constraints among those defining "map" that are valid | ||||||||||||
3437 | * for the context. These can then be used to simplify away | ||||||||||||
3438 | * the corresponding constraints in "map". | ||||||||||||
3439 | */ | ||||||||||||
3440 | static __isl_give isl_map *map_gist(__isl_take isl_map *map, | ||||||||||||
3441 | __isl_take isl_map *context) | ||||||||||||
3442 | { | ||||||||||||
3443 | int equal; | ||||||||||||
3444 | int is_universe; | ||||||||||||
3445 | int single_disjunct_map, single_disjunct_context; | ||||||||||||
3446 | isl_bool subset; | ||||||||||||
3447 | isl_basic_map *hull; | ||||||||||||
3448 | |||||||||||||
3449 | is_universe = isl_map_plain_is_universe(map); | ||||||||||||
3450 | if (is_universe >= 0 && !is_universe) | ||||||||||||
3451 | is_universe = isl_map_plain_is_universe(context); | ||||||||||||
3452 | if (is_universe < 0) | ||||||||||||
3453 | goto error; | ||||||||||||
3454 | if (is_universe) { | ||||||||||||
3455 | isl_map_free(context); | ||||||||||||
3456 | return map; | ||||||||||||
3457 | } | ||||||||||||
3458 | |||||||||||||
3459 | equal = isl_map_plain_is_equal(map, context); | ||||||||||||
3460 | if (equal < 0) | ||||||||||||
3461 | goto error; | ||||||||||||
3462 | if (equal) | ||||||||||||
3463 | return replace_by_universe(map, context); | ||||||||||||
3464 | |||||||||||||
3465 | single_disjunct_map = isl_map_n_basic_map(map) == 1; | ||||||||||||
3466 | single_disjunct_context = isl_map_n_basic_map(context) == 1; | ||||||||||||
3467 | if (!single_disjunct_map || !single_disjunct_context) { | ||||||||||||
3468 | subset = isl_map_is_subset(context, map); | ||||||||||||
3469 | if (subset < 0) | ||||||||||||
3470 | goto error; | ||||||||||||
3471 | if (subset) | ||||||||||||
3472 | return replace_by_universe(map, context); | ||||||||||||
3473 | } | ||||||||||||
3474 | |||||||||||||
3475 | context = isl_map_compute_divs(context); | ||||||||||||
3476 | if (!context) | ||||||||||||
3477 | goto error; | ||||||||||||
3478 | if (single_disjunct_context) { | ||||||||||||
3479 | hull = isl_map_simple_hull(context); | ||||||||||||
3480 | } else { | ||||||||||||
3481 | isl_ctx *ctx; | ||||||||||||
3482 | isl_map_list *list; | ||||||||||||
3483 | |||||||||||||
3484 | ctx = isl_map_get_ctx(map); | ||||||||||||
3485 | list = isl_map_list_alloc(ctx, 2); | ||||||||||||
3486 | list = isl_map_list_add(list, isl_map_copy(context)); | ||||||||||||
3487 | list = isl_map_list_add(list, isl_map_copy(map)); | ||||||||||||
3488 | hull = isl_map_unshifted_simple_hull_from_map_list(context, | ||||||||||||
3489 | list); | ||||||||||||
3490 | } | ||||||||||||
3491 | return isl_map_gist_basic_map(map, hull); | ||||||||||||
3492 | error: | ||||||||||||
3493 | isl_map_free(map); | ||||||||||||
3494 | isl_map_free(context); | ||||||||||||
3495 | return NULL((void*)0); | ||||||||||||
3496 | } | ||||||||||||
3497 | |||||||||||||
3498 | __isl_give isl_map *isl_map_gist(__isl_take isl_map *map, | ||||||||||||
3499 | __isl_take isl_map *context) | ||||||||||||
3500 | { | ||||||||||||
3501 | return isl_map_align_params_map_map_and(map, context, &map_gist); | ||||||||||||
3502 | } | ||||||||||||
3503 | |||||||||||||
3504 | struct isl_basic_setisl_basic_map *isl_basic_set_gist(struct isl_basic_setisl_basic_map *bset, | ||||||||||||
3505 | struct isl_basic_setisl_basic_map *context) | ||||||||||||
3506 | { | ||||||||||||
3507 | return bset_from_bmap(isl_basic_map_gist(bset_to_bmap(bset), | ||||||||||||
3508 | bset_to_bmap(context))); | ||||||||||||
3509 | } | ||||||||||||
3510 | |||||||||||||
3511 | __isl_give isl_setisl_map *isl_set_gist_basic_set(__isl_take isl_setisl_map *set, | ||||||||||||
3512 | __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
3513 | { | ||||||||||||
3514 | return set_from_map(isl_map_gist_basic_map(set_to_map(set), | ||||||||||||
3515 | bset_to_bmap(context))); | ||||||||||||
3516 | } | ||||||||||||
3517 | |||||||||||||
3518 | __isl_give isl_setisl_map *isl_set_gist_params_basic_set(__isl_take isl_setisl_map *set, | ||||||||||||
3519 | __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
3520 | { | ||||||||||||
3521 | isl_space *space = isl_set_get_space(set); | ||||||||||||
3522 | isl_basic_setisl_basic_map *dom_context = isl_basic_set_universe(space); | ||||||||||||
3523 | dom_context = isl_basic_set_intersect_params(dom_context, context); | ||||||||||||
3524 | return isl_set_gist_basic_set(set, dom_context); | ||||||||||||
3525 | } | ||||||||||||
3526 | |||||||||||||
3527 | __isl_give isl_setisl_map *isl_set_gist(__isl_take isl_setisl_map *set, | ||||||||||||
3528 | __isl_take isl_setisl_map *context) | ||||||||||||
3529 | { | ||||||||||||
3530 | return set_from_map(isl_map_gist(set_to_map(set), set_to_map(context))); | ||||||||||||
3531 | } | ||||||||||||
3532 | |||||||||||||
3533 | /* Compute the gist of "bmap" with respect to the constraints "context" | ||||||||||||
3534 | * on the domain. | ||||||||||||
3535 | */ | ||||||||||||
3536 | __isl_give isl_basic_map *isl_basic_map_gist_domain( | ||||||||||||
3537 | __isl_take isl_basic_map *bmap, __isl_take isl_basic_setisl_basic_map *context) | ||||||||||||
3538 | { | ||||||||||||
3539 | isl_space *space = isl_basic_map_get_space(bmap); | ||||||||||||
3540 | isl_basic_map *bmap_context = isl_basic_map_universe(space); | ||||||||||||
3541 | |||||||||||||
3542 | bmap_context = isl_basic_map_intersect_domain(bmap_context, context); | ||||||||||||
3543 | return isl_basic_map_gist(bmap, bmap_context); | ||||||||||||
3544 | } | ||||||||||||
3545 | |||||||||||||
3546 | __isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map, | ||||||||||||
3547 | __isl_take isl_setisl_map *context) | ||||||||||||
3548 | { | ||||||||||||
3549 | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); | ||||||||||||
3550 | map_context = isl_map_intersect_domain(map_context, context); | ||||||||||||
3551 | return isl_map_gist(map, map_context); | ||||||||||||
3552 | } | ||||||||||||
3553 | |||||||||||||
3554 | __isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map, | ||||||||||||
3555 | __isl_take isl_setisl_map *context) | ||||||||||||
3556 | { | ||||||||||||
3557 | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); | ||||||||||||
3558 | map_context = isl_map_intersect_range(map_context, context); | ||||||||||||
3559 | return isl_map_gist(map, map_context); | ||||||||||||
3560 | } | ||||||||||||
3561 | |||||||||||||
3562 | __isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map, | ||||||||||||
3563 | __isl_take isl_setisl_map *context) | ||||||||||||
3564 | { | ||||||||||||
3565 | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); | ||||||||||||
3566 | map_context = isl_map_intersect_params(map_context, context); | ||||||||||||
3567 | return isl_map_gist(map, map_context); | ||||||||||||
3568 | } | ||||||||||||
3569 | |||||||||||||
3570 | __isl_give isl_setisl_map *isl_set_gist_params(__isl_take isl_setisl_map *set, | ||||||||||||
3571 | __isl_take isl_setisl_map *context) | ||||||||||||
3572 | { | ||||||||||||
3573 | return isl_map_gist_params(set, context); | ||||||||||||
3574 | } | ||||||||||||
3575 | |||||||||||||
3576 | /* Quick check to see if two basic maps are disjoint. | ||||||||||||
3577 | * In particular, we reduce the equalities and inequalities of | ||||||||||||
3578 | * one basic map in the context of the equalities of the other | ||||||||||||
3579 | * basic map and check if we get a contradiction. | ||||||||||||
3580 | */ | ||||||||||||
3581 | isl_bool isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1, | ||||||||||||
3582 | __isl_keep isl_basic_map *bmap2) | ||||||||||||
3583 | { | ||||||||||||
3584 | struct isl_vec *v = NULL((void*)0); | ||||||||||||
3585 | int *elim = NULL((void*)0); | ||||||||||||
3586 | unsigned total; | ||||||||||||
3587 | int i; | ||||||||||||
3588 | |||||||||||||
3589 | if (!bmap1 || !bmap2) | ||||||||||||
3590 | return isl_bool_error; | ||||||||||||
3591 | isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),do { if (isl_space_is_equal(bmap1->dim, bmap2->dim)) break ; do { isl_handle_error(bmap1->ctx, isl_error_unknown, "Assertion \"" "isl_space_is_equal(bmap1->dim, bmap2->dim)" "\" failed" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3592); return isl_bool_error; } while (0); } while (0) | ||||||||||||
3592 | return isl_bool_error)do { if (isl_space_is_equal(bmap1->dim, bmap2->dim)) break ; do { isl_handle_error(bmap1->ctx, isl_error_unknown, "Assertion \"" "isl_space_is_equal(bmap1->dim, bmap2->dim)" "\" failed" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 3592); return isl_bool_error; } while (0); } while (0); | ||||||||||||
3593 | if (bmap1->n_div || bmap2->n_div) | ||||||||||||
3594 | return isl_bool_false; | ||||||||||||
3595 | if (!bmap1->n_eq && !bmap2->n_eq) | ||||||||||||
3596 | return isl_bool_false; | ||||||||||||
3597 | |||||||||||||
3598 | total = isl_space_dim(bmap1->dim, isl_dim_all); | ||||||||||||
3599 | if (total == 0) | ||||||||||||
3600 | return isl_bool_false; | ||||||||||||
3601 | v = isl_vec_alloc(bmap1->ctx, 1 + total); | ||||||||||||
3602 | if (!v) | ||||||||||||
3603 | goto error; | ||||||||||||
3604 | elim = isl_alloc_array(bmap1->ctx, int, total)((int *)isl_malloc_or_die(bmap1->ctx, (total)*sizeof(int)) ); | ||||||||||||
3605 | if (!elim) | ||||||||||||
3606 | goto error; | ||||||||||||
3607 | compute_elimination_index(bmap1, elim); | ||||||||||||
3608 | for (i = 0; i < bmap2->n_eq; ++i) { | ||||||||||||
3609 | int reduced; | ||||||||||||
3610 | reduced = reduced_using_equalities(v->block.data, bmap2->eq[i], | ||||||||||||
3611 | bmap1, elim); | ||||||||||||
3612 | if (reduced && !isl_int_is_zero(v->block.data[0])(isl_sioimath_sgn(*(v->block.data[0])) == 0) && | ||||||||||||
3613 | isl_seq_first_non_zero(v->block.data + 1, total) == -1) | ||||||||||||
3614 | goto disjoint; | ||||||||||||
3615 | } | ||||||||||||
3616 | for (i = 0; i < bmap2->n_ineq; ++i) { | ||||||||||||
3617 | int reduced; | ||||||||||||
3618 | reduced = reduced_using_equalities(v->block.data, | ||||||||||||
3619 | bmap2->ineq[i], bmap1, elim); | ||||||||||||
3620 | if (reduced && isl_int_is_neg(v->block.data[0])(isl_sioimath_sgn(*(v->block.data[0])) < 0) && | ||||||||||||
3621 | isl_seq_first_non_zero(v->block.data + 1, total) == -1) | ||||||||||||
3622 | goto disjoint; | ||||||||||||
3623 | } | ||||||||||||
3624 | compute_elimination_index(bmap2, elim); | ||||||||||||
3625 | for (i = 0; i < bmap1->n_ineq; ++i) { | ||||||||||||
3626 | int reduced; | ||||||||||||
3627 | reduced = reduced_using_equalities(v->block.data, | ||||||||||||
3628 | bmap1->ineq[i], bmap2, elim); | ||||||||||||
3629 | if (reduced && isl_int_is_neg(v->block.data[0])(isl_sioimath_sgn(*(v->block.data[0])) < 0) && | ||||||||||||
3630 | isl_seq_first_non_zero(v->block.data + 1, total) == -1) | ||||||||||||
3631 | goto disjoint; | ||||||||||||
3632 | } | ||||||||||||
3633 | isl_vec_free(v); | ||||||||||||
3634 | free(elim); | ||||||||||||
3635 | return isl_bool_false; | ||||||||||||
3636 | disjoint: | ||||||||||||
3637 | isl_vec_free(v); | ||||||||||||
3638 | free(elim); | ||||||||||||
3639 | return isl_bool_true; | ||||||||||||
3640 | error: | ||||||||||||
3641 | isl_vec_free(v); | ||||||||||||
3642 | free(elim); | ||||||||||||
3643 | return isl_bool_error; | ||||||||||||
3644 | } | ||||||||||||
3645 | |||||||||||||
3646 | int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_setisl_basic_map *bset1, | ||||||||||||
3647 | __isl_keep isl_basic_setisl_basic_map *bset2) | ||||||||||||
3648 | { | ||||||||||||
3649 | return isl_basic_map_plain_is_disjoint(bset_to_bmap(bset1), | ||||||||||||
3650 | bset_to_bmap(bset2)); | ||||||||||||
3651 | } | ||||||||||||
3652 | |||||||||||||
3653 | /* Does "test" hold for all pairs of basic maps in "map1" and "map2"? | ||||||||||||
3654 | */ | ||||||||||||
3655 | static isl_bool all_pairs(__isl_keep isl_map *map1, __isl_keep isl_map *map2, | ||||||||||||
3656 | isl_bool (*test)(__isl_keep isl_basic_map *bmap1, | ||||||||||||
3657 | __isl_keep isl_basic_map *bmap2)) | ||||||||||||
3658 | { | ||||||||||||
3659 | int i, j; | ||||||||||||
3660 | |||||||||||||
3661 | if (!map1 || !map2) | ||||||||||||
3662 | return isl_bool_error; | ||||||||||||
3663 | |||||||||||||
3664 | for (i = 0; i < map1->n; ++i) { | ||||||||||||
3665 | for (j = 0; j < map2->n; ++j) { | ||||||||||||
3666 | isl_bool d = test(map1->p[i], map2->p[j]); | ||||||||||||
3667 | if (d != isl_bool_true) | ||||||||||||
3668 | return d; | ||||||||||||
3669 | } | ||||||||||||
3670 | } | ||||||||||||
3671 | |||||||||||||
3672 | return isl_bool_true; | ||||||||||||
3673 | } | ||||||||||||
3674 | |||||||||||||
3675 | /* Are "map1" and "map2" obviously disjoint, based on information | ||||||||||||
3676 | * that can be derived without looking at the individual basic maps? | ||||||||||||
3677 | * | ||||||||||||
3678 | * In particular, if one of them is empty or if they live in different spaces | ||||||||||||
3679 | * (ignoring parameters), then they are clearly disjoint. | ||||||||||||
3680 | */ | ||||||||||||
3681 | static isl_bool isl_map_plain_is_disjoint_global(__isl_keep isl_map *map1, | ||||||||||||
3682 | __isl_keep isl_map *map2) | ||||||||||||
3683 | { | ||||||||||||
3684 | isl_bool disjoint; | ||||||||||||
3685 | isl_bool match; | ||||||||||||
3686 | |||||||||||||
3687 | if (!map1 || !map2) | ||||||||||||
3688 | return isl_bool_error; | ||||||||||||
3689 | |||||||||||||
3690 | disjoint = isl_map_plain_is_empty(map1); | ||||||||||||
3691 | if (disjoint < 0 || disjoint) | ||||||||||||
3692 | return disjoint; | ||||||||||||
3693 | |||||||||||||
3694 | disjoint = isl_map_plain_is_empty(map2); | ||||||||||||
3695 | if (disjoint < 0 || disjoint) | ||||||||||||
3696 | return disjoint; | ||||||||||||
3697 | |||||||||||||
3698 | match = isl_space_tuple_is_equal(map1->dim, isl_dim_in, | ||||||||||||
3699 | map2->dim, isl_dim_in); | ||||||||||||
3700 | if (match < 0 || !match) | ||||||||||||
3701 | return match < 0 ? isl_bool_error : isl_bool_true; | ||||||||||||
3702 | |||||||||||||
3703 | match = isl_space_tuple_is_equal(map1->dim, isl_dim_out, | ||||||||||||
3704 | map2->dim, isl_dim_out); | ||||||||||||
3705 | if (match < 0 || !match) | ||||||||||||
3706 | return match < 0 ? isl_bool_error : isl_bool_true; | ||||||||||||
3707 | |||||||||||||
3708 | return isl_bool_false; | ||||||||||||
3709 | } | ||||||||||||
3710 | |||||||||||||
3711 | /* Are "map1" and "map2" obviously disjoint? | ||||||||||||
3712 | * | ||||||||||||
3713 | * If one of them is empty or if they live in different spaces (ignoring | ||||||||||||
3714 | * parameters), then they are clearly disjoint. | ||||||||||||
3715 | * This is checked by isl_map_plain_is_disjoint_global. | ||||||||||||
3716 | * | ||||||||||||
3717 | * If they have different parameters, then we skip any further tests. | ||||||||||||
3718 | * | ||||||||||||
3719 | * If they are obviously equal, but not obviously empty, then we will | ||||||||||||
3720 | * not be able to detect if they are disjoint. | ||||||||||||
3721 | * | ||||||||||||
3722 | * Otherwise we check if each basic map in "map1" is obviously disjoint | ||||||||||||
3723 | * from each basic map in "map2". | ||||||||||||
3724 | */ | ||||||||||||
3725 | isl_bool isl_map_plain_is_disjoint(__isl_keep isl_map *map1, | ||||||||||||
3726 | __isl_keep isl_map *map2) | ||||||||||||
3727 | { | ||||||||||||
3728 | isl_bool disjoint; | ||||||||||||
3729 | isl_bool intersect; | ||||||||||||
3730 | isl_bool match; | ||||||||||||
3731 | |||||||||||||
3732 | disjoint = isl_map_plain_is_disjoint_global(map1, map2); | ||||||||||||
3733 | if (disjoint < 0 || disjoint) | ||||||||||||
3734 | return disjoint; | ||||||||||||
3735 | |||||||||||||
3736 | match = isl_map_has_equal_params(map1, map2); | ||||||||||||
3737 | if (match < 0 || !match) | ||||||||||||
3738 | return match < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3739 | |||||||||||||
3740 | intersect = isl_map_plain_is_equal(map1, map2); | ||||||||||||
3741 | if (intersect < 0 || intersect) | ||||||||||||
3742 | return intersect < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3743 | |||||||||||||
3744 | return all_pairs(map1, map2, &isl_basic_map_plain_is_disjoint); | ||||||||||||
3745 | } | ||||||||||||
3746 | |||||||||||||
3747 | /* Are "map1" and "map2" disjoint? | ||||||||||||
3748 | * The parameters are assumed to have been aligned. | ||||||||||||
3749 | * | ||||||||||||
3750 | * In particular, check whether all pairs of basic maps are disjoint. | ||||||||||||
3751 | */ | ||||||||||||
3752 | static isl_bool isl_map_is_disjoint_aligned(__isl_keep isl_map *map1, | ||||||||||||
3753 | __isl_keep isl_map *map2) | ||||||||||||
3754 | { | ||||||||||||
3755 | return all_pairs(map1, map2, &isl_basic_map_is_disjoint); | ||||||||||||
3756 | } | ||||||||||||
3757 | |||||||||||||
3758 | /* Are "map1" and "map2" disjoint? | ||||||||||||
3759 | * | ||||||||||||
3760 | * They are disjoint if they are "obviously disjoint" or if one of them | ||||||||||||
3761 | * is empty. Otherwise, they are not disjoint if one of them is universal. | ||||||||||||
3762 | * If the two inputs are (obviously) equal and not empty, then they are | ||||||||||||
3763 | * not disjoint. | ||||||||||||
3764 | * If none of these cases apply, then check if all pairs of basic maps | ||||||||||||
3765 | * are disjoint after aligning the parameters. | ||||||||||||
3766 | */ | ||||||||||||
3767 | isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2) | ||||||||||||
3768 | { | ||||||||||||
3769 | isl_bool disjoint; | ||||||||||||
3770 | isl_bool intersect; | ||||||||||||
3771 | |||||||||||||
3772 | disjoint = isl_map_plain_is_disjoint_global(map1, map2); | ||||||||||||
3773 | if (disjoint < 0 || disjoint) | ||||||||||||
3774 | return disjoint; | ||||||||||||
3775 | |||||||||||||
3776 | disjoint = isl_map_is_empty(map1); | ||||||||||||
3777 | if (disjoint < 0 || disjoint) | ||||||||||||
3778 | return disjoint; | ||||||||||||
3779 | |||||||||||||
3780 | disjoint = isl_map_is_empty(map2); | ||||||||||||
3781 | if (disjoint < 0 || disjoint) | ||||||||||||
3782 | return disjoint; | ||||||||||||
3783 | |||||||||||||
3784 | intersect = isl_map_plain_is_universe(map1); | ||||||||||||
3785 | if (intersect < 0 || intersect) | ||||||||||||
3786 | return intersect < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3787 | |||||||||||||
3788 | intersect = isl_map_plain_is_universe(map2); | ||||||||||||
3789 | if (intersect < 0 || intersect) | ||||||||||||
3790 | return intersect < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3791 | |||||||||||||
3792 | intersect = isl_map_plain_is_equal(map1, map2); | ||||||||||||
3793 | if (intersect < 0 || intersect) | ||||||||||||
3794 | return isl_bool_not(intersect); | ||||||||||||
3795 | |||||||||||||
3796 | return isl_map_align_params_map_map_and_test(map1, map2, | ||||||||||||
3797 | &isl_map_is_disjoint_aligned); | ||||||||||||
3798 | } | ||||||||||||
3799 | |||||||||||||
3800 | /* Are "bmap1" and "bmap2" disjoint? | ||||||||||||
3801 | * | ||||||||||||
3802 | * They are disjoint if they are "obviously disjoint" or if one of them | ||||||||||||
3803 | * is empty. Otherwise, they are not disjoint if one of them is universal. | ||||||||||||
3804 | * If none of these cases apply, we compute the intersection and see if | ||||||||||||
3805 | * the result is empty. | ||||||||||||
3806 | */ | ||||||||||||
3807 | isl_bool isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1, | ||||||||||||
3808 | __isl_keep isl_basic_map *bmap2) | ||||||||||||
3809 | { | ||||||||||||
3810 | isl_bool disjoint; | ||||||||||||
3811 | isl_bool intersect; | ||||||||||||
3812 | isl_basic_map *test; | ||||||||||||
3813 | |||||||||||||
3814 | disjoint = isl_basic_map_plain_is_disjoint(bmap1, bmap2); | ||||||||||||
3815 | if (disjoint < 0 || disjoint) | ||||||||||||
3816 | return disjoint; | ||||||||||||
3817 | |||||||||||||
3818 | disjoint = isl_basic_map_is_empty(bmap1); | ||||||||||||
3819 | if (disjoint < 0 || disjoint) | ||||||||||||
3820 | return disjoint; | ||||||||||||
3821 | |||||||||||||
3822 | disjoint = isl_basic_map_is_empty(bmap2); | ||||||||||||
3823 | if (disjoint < 0 || disjoint) | ||||||||||||
3824 | return disjoint; | ||||||||||||
3825 | |||||||||||||
3826 | intersect = isl_basic_map_plain_is_universe(bmap1); | ||||||||||||
3827 | if (intersect < 0 || intersect) | ||||||||||||
3828 | return intersect < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3829 | |||||||||||||
3830 | intersect = isl_basic_map_plain_is_universe(bmap2); | ||||||||||||
3831 | if (intersect < 0 || intersect) | ||||||||||||
3832 | return intersect < 0 ? isl_bool_error : isl_bool_false; | ||||||||||||
3833 | |||||||||||||
3834 | test = isl_basic_map_intersect(isl_basic_map_copy(bmap1), | ||||||||||||
3835 | isl_basic_map_copy(bmap2)); | ||||||||||||
3836 | disjoint = isl_basic_map_is_empty(test); | ||||||||||||
3837 | isl_basic_map_free(test); | ||||||||||||
3838 | |||||||||||||
3839 | return disjoint; | ||||||||||||
3840 | } | ||||||||||||
3841 | |||||||||||||
3842 | /* Are "bset1" and "bset2" disjoint? | ||||||||||||
3843 | */ | ||||||||||||
3844 | isl_bool isl_basic_set_is_disjoint(__isl_keep isl_basic_setisl_basic_map *bset1, | ||||||||||||
3845 | __isl_keep isl_basic_setisl_basic_map *bset2) | ||||||||||||
3846 | { | ||||||||||||
3847 | return isl_basic_map_is_disjoint(bset1, bset2); | ||||||||||||
3848 | } | ||||||||||||
3849 | |||||||||||||
3850 | isl_bool isl_set_plain_is_disjoint(__isl_keep isl_setisl_map *set1, | ||||||||||||
3851 | __isl_keep isl_setisl_map *set2) | ||||||||||||
3852 | { | ||||||||||||
3853 | return isl_map_plain_is_disjoint(set_to_map(set1), set_to_map(set2)); | ||||||||||||
3854 | } | ||||||||||||
3855 | |||||||||||||
3856 | /* Are "set1" and "set2" disjoint? | ||||||||||||
3857 | */ | ||||||||||||
3858 | isl_bool isl_set_is_disjoint(__isl_keep isl_setisl_map *set1, __isl_keep isl_setisl_map *set2) | ||||||||||||
3859 | { | ||||||||||||
3860 | return isl_map_is_disjoint(set1, set2); | ||||||||||||
3861 | } | ||||||||||||
3862 | |||||||||||||
3863 | /* Is "v" equal to 0, 1 or -1? | ||||||||||||
3864 | */ | ||||||||||||
3865 | static int is_zero_or_one(isl_int v) | ||||||||||||
3866 | { | ||||||||||||
3867 | return isl_int_is_zero(v)(isl_sioimath_sgn(*(v)) == 0) || isl_int_is_one(v)(isl_sioimath_cmp_si(*(v), 1) == 0) || isl_int_is_negone(v)(isl_sioimath_cmp_si(*(v), -1) == 0); | ||||||||||||
3868 | } | ||||||||||||
3869 | |||||||||||||
3870 | /* Check if we can combine a given div with lower bound l and upper | ||||||||||||
3871 | * bound u with some other div and if so return that other div. | ||||||||||||
3872 | * Otherwise return -1. | ||||||||||||
3873 | * | ||||||||||||
3874 | * We first check that | ||||||||||||
3875 | * - the bounds are opposites of each other (except for the constant | ||||||||||||
3876 | * term) | ||||||||||||
3877 | * - the bounds do not reference any other div | ||||||||||||
3878 | * - no div is defined in terms of this div | ||||||||||||
3879 | * | ||||||||||||
3880 | * Let m be the size of the range allowed on the div by the bounds. | ||||||||||||
3881 | * That is, the bounds are of the form | ||||||||||||
3882 | * | ||||||||||||
3883 | * e <= a <= e + m - 1 | ||||||||||||
3884 | * | ||||||||||||
3885 | * with e some expression in the other variables. | ||||||||||||
3886 | * We look for another div b such that no third div is defined in terms | ||||||||||||
3887 | * of this second div b and such that in any constraint that contains | ||||||||||||
3888 | * a (except for the given lower and upper bound), also contains b | ||||||||||||
3889 | * with a coefficient that is m times that of b. | ||||||||||||
3890 | * That is, all constraints (except for the lower and upper bound) | ||||||||||||
3891 | * are of the form | ||||||||||||
3892 | * | ||||||||||||
3893 | * e + f (a + m b) >= 0 | ||||||||||||
3894 | * | ||||||||||||
3895 | * Furthermore, in the constraints that only contain b, the coefficient | ||||||||||||
3896 | * of b should be equal to 1 or -1. | ||||||||||||
3897 | * If so, we return b so that "a + m b" can be replaced by | ||||||||||||
3898 | * a single div "c = a + m b". | ||||||||||||
3899 | */ | ||||||||||||
3900 | static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs, | ||||||||||||
3901 | unsigned div, unsigned l, unsigned u) | ||||||||||||
3902 | { | ||||||||||||
3903 | int i, j; | ||||||||||||
3904 | unsigned dim; | ||||||||||||
3905 | int coalesce = -1; | ||||||||||||
3906 | |||||||||||||
3907 | if (bmap->n_div <= 1) | ||||||||||||
3908 | return -1; | ||||||||||||
3909 | dim = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
3910 | if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1) | ||||||||||||
3911 | return -1; | ||||||||||||
3912 | if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1, | ||||||||||||
3913 | bmap->n_div - div - 1) != -1) | ||||||||||||
3914 | return -1; | ||||||||||||
3915 | if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1, | ||||||||||||
3916 | dim + bmap->n_div)) | ||||||||||||
3917 | return -1; | ||||||||||||
3918 | |||||||||||||
3919 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
3920 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
3921 | continue; | ||||||||||||
3922 | if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div])(isl_sioimath_sgn(*(bmap->div[i][1 + 1 + dim + div])) == 0 )) | ||||||||||||
3923 | return -1; | ||||||||||||
3924 | } | ||||||||||||
3925 | |||||||||||||
3926 | isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0])isl_sioimath_add((bmap->ineq[l][0]), *(bmap->ineq[l][0] ), *(bmap->ineq[u][0])); | ||||||||||||
3927 | if (isl_int_is_neg(bmap->ineq[l][0])(isl_sioimath_sgn(*(bmap->ineq[l][0])) < 0)) { | ||||||||||||
3928 | isl_int_sub(bmap->ineq[l][0],isl_sioimath_sub((bmap->ineq[l][0]), *(bmap->ineq[l][0] ), *(bmap->ineq[u][0])) | ||||||||||||
3929 | bmap->ineq[l][0], bmap->ineq[u][0])isl_sioimath_sub((bmap->ineq[l][0]), *(bmap->ineq[l][0] ), *(bmap->ineq[u][0])); | ||||||||||||
3930 | bmap = isl_basic_map_copy(bmap); | ||||||||||||
3931 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
3932 | isl_basic_map_free(bmap); | ||||||||||||
3933 | return -1; | ||||||||||||
3934 | } | ||||||||||||
3935 | isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1)isl_sioimath_add_ui((bmap->ineq[l][0]), *(bmap->ineq[l] [0]), 1); | ||||||||||||
3936 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
3937 | if (i == div) | ||||||||||||
3938 | continue; | ||||||||||||
3939 | if (!pairs[i]) | ||||||||||||
3940 | continue; | ||||||||||||
3941 | for (j = 0; j < bmap->n_div; ++j) { | ||||||||||||
3942 | if (isl_int_is_zero(bmap->div[j][0])(isl_sioimath_sgn(*(bmap->div[j][0])) == 0)) | ||||||||||||
3943 | continue; | ||||||||||||
3944 | if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i])(isl_sioimath_sgn(*(bmap->div[j][1 + 1 + dim + i])) == 0)) | ||||||||||||
3945 | break; | ||||||||||||
3946 | } | ||||||||||||
3947 | if (j < bmap->n_div) | ||||||||||||
3948 | continue; | ||||||||||||
3949 | for (j = 0; j < bmap->n_ineq; ++j) { | ||||||||||||
3950 | int valid; | ||||||||||||
3951 | if (j == l || j == u) | ||||||||||||
3952 | continue; | ||||||||||||
3953 | if (isl_int_is_zero(bmap->ineq[j][1 + dim + div])(isl_sioimath_sgn(*(bmap->ineq[j][1 + dim + div])) == 0)) { | ||||||||||||
3954 | if (is_zero_or_one(bmap->ineq[j][1 + dim + i])) | ||||||||||||
3955 | continue; | ||||||||||||
3956 | break; | ||||||||||||
3957 | } | ||||||||||||
3958 | if (isl_int_is_zero(bmap->ineq[j][1 + dim + i])(isl_sioimath_sgn(*(bmap->ineq[j][1 + dim + i])) == 0)) | ||||||||||||
3959 | break; | ||||||||||||
3960 | isl_int_mul(bmap->ineq[j][1 + dim + div],isl_sioimath_mul((bmap->ineq[j][1 + dim + div]), *(bmap-> ineq[j][1 + dim + div]), *(bmap->ineq[l][0])) | ||||||||||||
3961 | bmap->ineq[j][1 + dim + div],isl_sioimath_mul((bmap->ineq[j][1 + dim + div]), *(bmap-> ineq[j][1 + dim + div]), *(bmap->ineq[l][0])) | ||||||||||||
3962 | bmap->ineq[l][0])isl_sioimath_mul((bmap->ineq[j][1 + dim + div]), *(bmap-> ineq[j][1 + dim + div]), *(bmap->ineq[l][0])); | ||||||||||||
3963 | valid = isl_int_eq(bmap->ineq[j][1 + dim + div],(isl_sioimath_cmp(*(bmap->ineq[j][1 + dim + div]), *(bmap-> ineq[j][1 + dim + i])) == 0) | ||||||||||||
3964 | bmap->ineq[j][1 + dim + i])(isl_sioimath_cmp(*(bmap->ineq[j][1 + dim + div]), *(bmap-> ineq[j][1 + dim + i])) == 0); | ||||||||||||
3965 | isl_int_divexact(bmap->ineq[j][1 + dim + div],isl_sioimath_tdiv_q((bmap->ineq[j][1 + dim + div]), *(bmap ->ineq[j][1 + dim + div]), *(bmap->ineq[l][0])) | ||||||||||||
3966 | bmap->ineq[j][1 + dim + div],isl_sioimath_tdiv_q((bmap->ineq[j][1 + dim + div]), *(bmap ->ineq[j][1 + dim + div]), *(bmap->ineq[l][0])) | ||||||||||||
3967 | bmap->ineq[l][0])isl_sioimath_tdiv_q((bmap->ineq[j][1 + dim + div]), *(bmap ->ineq[j][1 + dim + div]), *(bmap->ineq[l][0])); | ||||||||||||
3968 | if (!valid) | ||||||||||||
3969 | break; | ||||||||||||
3970 | } | ||||||||||||
3971 | if (j < bmap->n_ineq) | ||||||||||||
3972 | continue; | ||||||||||||
3973 | coalesce = i; | ||||||||||||
3974 | break; | ||||||||||||
3975 | } | ||||||||||||
3976 | isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1)isl_sioimath_sub_ui((bmap->ineq[l][0]), *(bmap->ineq[l] [0]), 1); | ||||||||||||
3977 | isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0])isl_sioimath_sub((bmap->ineq[l][0]), *(bmap->ineq[l][0] ), *(bmap->ineq[u][0])); | ||||||||||||
3978 | return coalesce; | ||||||||||||
3979 | } | ||||||||||||
3980 | |||||||||||||
3981 | /* Internal data structure used during the construction and/or evaluation of | ||||||||||||
3982 | * an inequality that ensures that a pair of bounds always allows | ||||||||||||
3983 | * for an integer value. | ||||||||||||
3984 | * | ||||||||||||
3985 | * "tab" is the tableau in which the inequality is evaluated. It may | ||||||||||||
3986 | * be NULL until it is actually needed. | ||||||||||||
3987 | * "v" contains the inequality coefficients. | ||||||||||||
3988 | * "g", "fl" and "fu" are temporary scalars used during the construction and | ||||||||||||
3989 | * evaluation. | ||||||||||||
3990 | */ | ||||||||||||
3991 | struct test_ineq_data { | ||||||||||||
3992 | struct isl_tab *tab; | ||||||||||||
3993 | isl_vec *v; | ||||||||||||
3994 | isl_int g; | ||||||||||||
3995 | isl_int fl; | ||||||||||||
3996 | isl_int fu; | ||||||||||||
3997 | }; | ||||||||||||
3998 | |||||||||||||
3999 | /* Free all the memory allocated by the fields of "data". | ||||||||||||
4000 | */ | ||||||||||||
4001 | static void test_ineq_data_clear(struct test_ineq_data *data) | ||||||||||||
4002 | { | ||||||||||||
4003 | isl_tab_free(data->tab); | ||||||||||||
4004 | isl_vec_free(data->v); | ||||||||||||
4005 | isl_int_clear(data->g)isl_sioimath_clear((data->g)); | ||||||||||||
4006 | isl_int_clear(data->fl)isl_sioimath_clear((data->fl)); | ||||||||||||
4007 | isl_int_clear(data->fu)isl_sioimath_clear((data->fu)); | ||||||||||||
4008 | } | ||||||||||||
4009 | |||||||||||||
4010 | /* Is the inequality stored in data->v satisfied by "bmap"? | ||||||||||||
4011 | * That is, does it only attain non-negative values? | ||||||||||||
4012 | * data->tab is a tableau corresponding to "bmap". | ||||||||||||
4013 | */ | ||||||||||||
4014 | static isl_bool test_ineq_is_satisfied(__isl_keep isl_basic_map *bmap, | ||||||||||||
4015 | struct test_ineq_data *data) | ||||||||||||
4016 | { | ||||||||||||
4017 | isl_ctx *ctx; | ||||||||||||
4018 | enum isl_lp_result res; | ||||||||||||
4019 | |||||||||||||
4020 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
4021 | if (!data->tab) | ||||||||||||
4022 | data->tab = isl_tab_from_basic_map(bmap, 0); | ||||||||||||
4023 | res = isl_tab_min(data->tab, data->v->el, ctx->one, &data->g, NULL((void*)0), 0); | ||||||||||||
4024 | if (res == isl_lp_error) | ||||||||||||
4025 | return isl_bool_error; | ||||||||||||
4026 | return res == isl_lp_ok && isl_int_is_nonneg(data->g)(isl_sioimath_sgn(*(data->g)) >= 0); | ||||||||||||
4027 | } | ||||||||||||
4028 | |||||||||||||
4029 | /* Given a lower and an upper bound on div i, do they always allow | ||||||||||||
4030 | * for an integer value of the given div? | ||||||||||||
4031 | * Determine this property by constructing an inequality | ||||||||||||
4032 | * such that the property is guaranteed when the inequality is nonnegative. | ||||||||||||
4033 | * The lower bound is inequality l, while the upper bound is inequality u. | ||||||||||||
4034 | * The constructed inequality is stored in data->v. | ||||||||||||
4035 | * | ||||||||||||
4036 | * Let the upper bound be | ||||||||||||
4037 | * | ||||||||||||
4038 | * -n_u a + e_u >= 0 | ||||||||||||
4039 | * | ||||||||||||
4040 | * and the lower bound | ||||||||||||
4041 | * | ||||||||||||
4042 | * n_l a + e_l >= 0 | ||||||||||||
4043 | * | ||||||||||||
4044 | * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l). | ||||||||||||
4045 | * We have | ||||||||||||
4046 | * | ||||||||||||
4047 | * - f_u e_l <= f_u f_l g a <= f_l e_u | ||||||||||||
4048 | * | ||||||||||||
4049 | * Since all variables are integer valued, this is equivalent to | ||||||||||||
4050 | * | ||||||||||||
4051 | * - f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1) | ||||||||||||
4052 | * | ||||||||||||
4053 | * If this interval is at least f_u f_l g, then it contains at least | ||||||||||||
4054 | * one integer value for a. | ||||||||||||
4055 | * That is, the test constraint is | ||||||||||||
4056 | * | ||||||||||||
4057 | * f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g | ||||||||||||
4058 | * | ||||||||||||
4059 | * or | ||||||||||||
4060 | * | ||||||||||||
4061 | * f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 - f_u f_l g >= 0 | ||||||||||||
4062 | * | ||||||||||||
4063 | * If the coefficients of f_l e_u + f_u e_l have a common divisor g', | ||||||||||||
4064 | * then the constraint can be scaled down by a factor g', | ||||||||||||
4065 | * with the constant term replaced by | ||||||||||||
4066 | * floor((f_l e_{u,0} + f_u e_{l,0} + f_l - 1 + f_u - 1 + 1 - f_u f_l g)/g'). | ||||||||||||
4067 | * Note that the result of applying Fourier-Motzkin to this pair | ||||||||||||
4068 | * of constraints is | ||||||||||||
4069 | * | ||||||||||||
4070 | * f_l e_u + f_u e_l >= 0 | ||||||||||||
4071 | * | ||||||||||||
4072 | * If the constant term of the scaled down version of this constraint, | ||||||||||||
4073 | * i.e., floor((f_l e_{u,0} + f_u e_{l,0})/g') is equal to the constant | ||||||||||||
4074 | * term of the scaled down test constraint, then the test constraint | ||||||||||||
4075 | * is known to hold and no explicit evaluation is required. | ||||||||||||
4076 | * This is essentially the Omega test. | ||||||||||||
4077 | * | ||||||||||||
4078 | * If the test constraint consists of only a constant term, then | ||||||||||||
4079 | * it is sufficient to look at the sign of this constant term. | ||||||||||||
4080 | */ | ||||||||||||
4081 | static isl_bool int_between_bounds(__isl_keep isl_basic_map *bmap, int i, | ||||||||||||
4082 | int l, int u, struct test_ineq_data *data) | ||||||||||||
4083 | { | ||||||||||||
4084 | unsigned offset, n_div; | ||||||||||||
4085 | offset = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4086 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
4087 | |||||||||||||
4088 | isl_int_gcd(data->g,isl_sioimath_gcd((data->g), *(bmap->ineq[l][offset + i] ), *(bmap->ineq[u][offset + i])) | ||||||||||||
4089 | bmap->ineq[l][offset + i], bmap->ineq[u][offset + i])isl_sioimath_gcd((data->g), *(bmap->ineq[l][offset + i] ), *(bmap->ineq[u][offset + i])); | ||||||||||||
4090 | isl_int_divexact(data->fl, bmap->ineq[l][offset + i], data->g)isl_sioimath_tdiv_q((data->fl), *(bmap->ineq[l][offset + i]), *(data->g)); | ||||||||||||
4091 | isl_int_divexact(data->fu, bmap->ineq[u][offset + i], data->g)isl_sioimath_tdiv_q((data->fu), *(bmap->ineq[u][offset + i]), *(data->g)); | ||||||||||||
4092 | isl_int_neg(data->fu, data->fu)isl_sioimath_neg((data->fu), *(data->fu)); | ||||||||||||
4093 | isl_seq_combine(data->v->el, data->fl, bmap->ineq[u], | ||||||||||||
4094 | data->fu, bmap->ineq[l], offset + n_div); | ||||||||||||
4095 | isl_int_mul(data->g, data->g, data->fl)isl_sioimath_mul((data->g), *(data->g), *(data->fl)); | ||||||||||||
4096 | isl_int_mul(data->g, data->g, data->fu)isl_sioimath_mul((data->g), *(data->g), *(data->fu)); | ||||||||||||
4097 | isl_int_sub(data->g, data->g, data->fl)isl_sioimath_sub((data->g), *(data->g), *(data->fl)); | ||||||||||||
4098 | isl_int_sub(data->g, data->g, data->fu)isl_sioimath_sub((data->g), *(data->g), *(data->fu)); | ||||||||||||
4099 | isl_int_add_ui(data->g, data->g, 1)isl_sioimath_add_ui((data->g), *(data->g), 1); | ||||||||||||
4100 | isl_int_sub(data->fl, data->v->el[0], data->g)isl_sioimath_sub((data->fl), *(data->v->el[0]), *(data ->g)); | ||||||||||||
4101 | |||||||||||||
4102 | isl_seq_gcd(data->v->el + 1, offset - 1 + n_div, &data->g); | ||||||||||||
4103 | if (isl_int_is_zero(data->g)(isl_sioimath_sgn(*(data->g)) == 0)) | ||||||||||||
4104 | return isl_int_is_nonneg(data->fl)(isl_sioimath_sgn(*(data->fl)) >= 0); | ||||||||||||
4105 | if (isl_int_is_one(data->g)(isl_sioimath_cmp_si(*(data->g), 1) == 0)) { | ||||||||||||
4106 | isl_int_set(data->v->el[0], data->fl)isl_sioimath_set((data->v->el[0]), *(data->fl)); | ||||||||||||
4107 | return test_ineq_is_satisfied(bmap, data); | ||||||||||||
4108 | } | ||||||||||||
4109 | isl_int_fdiv_q(data->fl, data->fl, data->g)isl_sioimath_fdiv_q((data->fl), *(data->fl), *(data-> g)); | ||||||||||||
4110 | isl_int_fdiv_q(data->v->el[0], data->v->el[0], data->g)isl_sioimath_fdiv_q((data->v->el[0]), *(data->v-> el[0]), *(data->g)); | ||||||||||||
4111 | if (isl_int_eq(data->fl, data->v->el[0])(isl_sioimath_cmp(*(data->fl), *(data->v->el[0])) == 0)) | ||||||||||||
4112 | return isl_bool_true; | ||||||||||||
4113 | isl_int_set(data->v->el[0], data->fl)isl_sioimath_set((data->v->el[0]), *(data->fl)); | ||||||||||||
4114 | isl_seq_scale_down(data->v->el + 1, data->v->el + 1, data->g, | ||||||||||||
4115 | offset - 1 + n_div); | ||||||||||||
4116 | |||||||||||||
4117 | return test_ineq_is_satisfied(bmap, data); | ||||||||||||
4118 | } | ||||||||||||
4119 | |||||||||||||
4120 | /* Remove more kinds of divs that are not strictly needed. | ||||||||||||
4121 | * In particular, if all pairs of lower and upper bounds on a div | ||||||||||||
4122 | * are such that they allow at least one integer value of the div, | ||||||||||||
4123 | * then we can eliminate the div using Fourier-Motzkin without | ||||||||||||
4124 | * introducing any spurious solutions. | ||||||||||||
4125 | * | ||||||||||||
4126 | * If at least one of the two constraints has a unit coefficient for the div, | ||||||||||||
4127 | * then the presence of such a value is guaranteed so there is no need to check. | ||||||||||||
4128 | * In particular, the value attained by the bound with unit coefficient | ||||||||||||
4129 | * can serve as this intermediate value. | ||||||||||||
4130 | */ | ||||||||||||
4131 | static __isl_give isl_basic_map *drop_more_redundant_divs( | ||||||||||||
4132 | __isl_take isl_basic_map *bmap, __isl_take int *pairs, int n) | ||||||||||||
4133 | { | ||||||||||||
4134 | isl_ctx *ctx; | ||||||||||||
4135 | struct test_ineq_data data = { NULL((void*)0), NULL((void*)0) }; | ||||||||||||
4136 | unsigned off, n_div; | ||||||||||||
4137 | int remove = -1; | ||||||||||||
4138 | |||||||||||||
4139 | isl_int_init(data.g)isl_sioimath_init((data.g)); | ||||||||||||
4140 | isl_int_init(data.fl)isl_sioimath_init((data.fl)); | ||||||||||||
4141 | isl_int_init(data.fu)isl_sioimath_init((data.fu)); | ||||||||||||
4142 | |||||||||||||
4143 | if (!bmap) | ||||||||||||
4144 | goto error; | ||||||||||||
4145 | |||||||||||||
4146 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
4147 | off = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4148 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
4149 | data.v = isl_vec_alloc(ctx, off + n_div); | ||||||||||||
4150 | if (!data.v) | ||||||||||||
4151 | goto error; | ||||||||||||
4152 | |||||||||||||
4153 | while (n > 0) { | ||||||||||||
4154 | int i, l, u; | ||||||||||||
4155 | int best = -1; | ||||||||||||
4156 | isl_bool has_int; | ||||||||||||
4157 | |||||||||||||
4158 | for (i = 0; i < n_div; ++i) { | ||||||||||||
4159 | if (!pairs[i]) | ||||||||||||
4160 | continue; | ||||||||||||
4161 | if (best >= 0 && pairs[best] <= pairs[i]) | ||||||||||||
4162 | continue; | ||||||||||||
4163 | best = i; | ||||||||||||
4164 | } | ||||||||||||
4165 | |||||||||||||
4166 | i = best; | ||||||||||||
4167 | for (l = 0; l < bmap->n_ineq; ++l) { | ||||||||||||
4168 | if (!isl_int_is_pos(bmap->ineq[l][off + i])(isl_sioimath_sgn(*(bmap->ineq[l][off + i])) > 0)) | ||||||||||||
4169 | continue; | ||||||||||||
4170 | if (isl_int_is_one(bmap->ineq[l][off + i])(isl_sioimath_cmp_si(*(bmap->ineq[l][off + i]), 1) == 0)) | ||||||||||||
4171 | continue; | ||||||||||||
4172 | for (u = 0; u < bmap->n_ineq; ++u) { | ||||||||||||
4173 | if (!isl_int_is_neg(bmap->ineq[u][off + i])(isl_sioimath_sgn(*(bmap->ineq[u][off + i])) < 0)) | ||||||||||||
4174 | continue; | ||||||||||||
4175 | if (isl_int_is_negone(bmap->ineq[u][off + i])(isl_sioimath_cmp_si(*(bmap->ineq[u][off + i]), -1) == 0)) | ||||||||||||
4176 | continue; | ||||||||||||
4177 | has_int = int_between_bounds(bmap, i, l, u, | ||||||||||||
4178 | &data); | ||||||||||||
4179 | if (has_int < 0) | ||||||||||||
4180 | goto error; | ||||||||||||
4181 | if (data.tab && data.tab->empty) | ||||||||||||
4182 | break; | ||||||||||||
4183 | if (!has_int) | ||||||||||||
4184 | break; | ||||||||||||
4185 | } | ||||||||||||
4186 | if (u < bmap->n_ineq) | ||||||||||||
4187 | break; | ||||||||||||
4188 | } | ||||||||||||
4189 | if (data.tab && data.tab->empty) { | ||||||||||||
4190 | bmap = isl_basic_map_set_to_empty(bmap); | ||||||||||||
4191 | break; | ||||||||||||
4192 | } | ||||||||||||
4193 | if (l == bmap->n_ineq) { | ||||||||||||
4194 | remove = i; | ||||||||||||
4195 | break; | ||||||||||||
4196 | } | ||||||||||||
4197 | pairs[i] = 0; | ||||||||||||
4198 | --n; | ||||||||||||
4199 | } | ||||||||||||
4200 | |||||||||||||
4201 | test_ineq_data_clear(&data); | ||||||||||||
4202 | |||||||||||||
4203 | free(pairs); | ||||||||||||
4204 | |||||||||||||
4205 | if (remove < 0) | ||||||||||||
4206 | return bmap; | ||||||||||||
4207 | |||||||||||||
4208 | bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1); | ||||||||||||
4209 | return isl_basic_map_drop_redundant_divs(bmap); | ||||||||||||
4210 | error: | ||||||||||||
4211 | free(pairs); | ||||||||||||
4212 | isl_basic_map_free(bmap); | ||||||||||||
4213 | test_ineq_data_clear(&data); | ||||||||||||
4214 | return NULL((void*)0); | ||||||||||||
4215 | } | ||||||||||||
4216 | |||||||||||||
4217 | /* Given a pair of divs div1 and div2 such that, except for the lower bound l | ||||||||||||
4218 | * and the upper bound u, div1 always occurs together with div2 in the form | ||||||||||||
4219 | * (div1 + m div2), where m is the constant range on the variable div1 | ||||||||||||
4220 | * allowed by l and u, replace the pair div1 and div2 by a single | ||||||||||||
4221 | * div that is equal to div1 + m div2. | ||||||||||||
4222 | * | ||||||||||||
4223 | * The new div will appear in the location that contains div2. | ||||||||||||
4224 | * We need to modify all constraints that contain | ||||||||||||
4225 | * div2 = (div - div1) / m | ||||||||||||
4226 | * The coefficient of div2 is known to be equal to 1 or -1. | ||||||||||||
4227 | * (If a constraint does not contain div2, it will also not contain div1.) | ||||||||||||
4228 | * If the constraint also contains div1, then we know they appear | ||||||||||||
4229 | * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div, | ||||||||||||
4230 | * i.e., the coefficient of div is f. | ||||||||||||
4231 | * | ||||||||||||
4232 | * Otherwise, we first need to introduce div1 into the constraint. | ||||||||||||
4233 | * Let l be | ||||||||||||
4234 | * | ||||||||||||
4235 | * div1 + f >=0 | ||||||||||||
4236 | * | ||||||||||||
4237 | * and u | ||||||||||||
4238 | * | ||||||||||||
4239 | * -div1 + f' >= 0 | ||||||||||||
4240 | * | ||||||||||||
4241 | * A lower bound on div2 | ||||||||||||
4242 | * | ||||||||||||
4243 | * div2 + t >= 0 | ||||||||||||
4244 | * | ||||||||||||
4245 | * can be replaced by | ||||||||||||
4246 | * | ||||||||||||
4247 | * m div2 + div1 + m t + f >= 0 | ||||||||||||
4248 | * | ||||||||||||
4249 | * An upper bound | ||||||||||||
4250 | * | ||||||||||||
4251 | * -div2 + t >= 0 | ||||||||||||
4252 | * | ||||||||||||
4253 | * can be replaced by | ||||||||||||
4254 | * | ||||||||||||
4255 | * -(m div2 + div1) + m t + f' >= 0 | ||||||||||||
4256 | * | ||||||||||||
4257 | * These constraint are those that we would obtain from eliminating | ||||||||||||
4258 | * div1 using Fourier-Motzkin. | ||||||||||||
4259 | * | ||||||||||||
4260 | * After all constraints have been modified, we drop the lower and upper | ||||||||||||
4261 | * bound and then drop div1. | ||||||||||||
4262 | * Since the new div is only placed in the same location that used | ||||||||||||
4263 | * to store div2, but otherwise has a different meaning, any possible | ||||||||||||
4264 | * explicit representation of the original div2 is removed. | ||||||||||||
4265 | */ | ||||||||||||
4266 | static __isl_give isl_basic_map *coalesce_divs(__isl_take isl_basic_map *bmap, | ||||||||||||
4267 | unsigned div1, unsigned div2, unsigned l, unsigned u) | ||||||||||||
4268 | { | ||||||||||||
4269 | isl_ctx *ctx; | ||||||||||||
4270 | isl_int m; | ||||||||||||
4271 | unsigned dim, total; | ||||||||||||
4272 | int i; | ||||||||||||
4273 | |||||||||||||
4274 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
4275 | |||||||||||||
4276 | dim = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
4277 | total = 1 + dim + bmap->n_div; | ||||||||||||
4278 | |||||||||||||
4279 | isl_int_init(m)isl_sioimath_init((m)); | ||||||||||||
4280 | isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0])isl_sioimath_add((m), *(bmap->ineq[l][0]), *(bmap->ineq [u][0])); | ||||||||||||
4281 | isl_int_add_ui(m, m, 1)isl_sioimath_add_ui((m), *(m), 1); | ||||||||||||
4282 | |||||||||||||
4283 | for (i = 0; i < bmap->n_ineq; ++i) { | ||||||||||||
4284 | if (i == l || i == u) | ||||||||||||
4285 | continue; | ||||||||||||
4286 | if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2])(isl_sioimath_sgn(*(bmap->ineq[i][1 + dim + div2])) == 0)) | ||||||||||||
4287 | continue; | ||||||||||||
4288 | if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])(isl_sioimath_sgn(*(bmap->ineq[i][1 + dim + div1])) == 0)) { | ||||||||||||
4289 | if (isl_int_is_pos(bmap->ineq[i][1 + dim + div2])(isl_sioimath_sgn(*(bmap->ineq[i][1 + dim + div2])) > 0 )) | ||||||||||||
4290 | isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i], | ||||||||||||
4291 | ctx->one, bmap->ineq[l], total); | ||||||||||||
4292 | else | ||||||||||||
4293 | isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i], | ||||||||||||
4294 | ctx->one, bmap->ineq[u], total); | ||||||||||||
4295 | } | ||||||||||||
4296 | isl_int_set(bmap->ineq[i][1 + dim + div2],isl_sioimath_set((bmap->ineq[i][1 + dim + div2]), *(bmap-> ineq[i][1 + dim + div1])) | ||||||||||||
4297 | bmap->ineq[i][1 + dim + div1])isl_sioimath_set((bmap->ineq[i][1 + dim + div2]), *(bmap-> ineq[i][1 + dim + div1])); | ||||||||||||
4298 | isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0)isl_sioimath_set_si((bmap->ineq[i][1 + dim + div1]), 0); | ||||||||||||
4299 | } | ||||||||||||
4300 | |||||||||||||
4301 | isl_int_clear(m)isl_sioimath_clear((m)); | ||||||||||||
4302 | if (l > u) { | ||||||||||||
4303 | isl_basic_map_drop_inequality(bmap, l); | ||||||||||||
4304 | isl_basic_map_drop_inequality(bmap, u); | ||||||||||||
4305 | } else { | ||||||||||||
4306 | isl_basic_map_drop_inequality(bmap, u); | ||||||||||||
4307 | isl_basic_map_drop_inequality(bmap, l); | ||||||||||||
4308 | } | ||||||||||||
4309 | bmap = isl_basic_map_mark_div_unknown(bmap, div2); | ||||||||||||
4310 | bmap = isl_basic_map_drop_div(bmap, div1); | ||||||||||||
4311 | return bmap; | ||||||||||||
4312 | } | ||||||||||||
4313 | |||||||||||||
4314 | /* First check if we can coalesce any pair of divs and | ||||||||||||
4315 | * then continue with dropping more redundant divs. | ||||||||||||
4316 | * | ||||||||||||
4317 | * We loop over all pairs of lower and upper bounds on a div | ||||||||||||
4318 | * with coefficient 1 and -1, respectively, check if there | ||||||||||||
4319 | * is any other div "c" with which we can coalesce the div | ||||||||||||
4320 | * and if so, perform the coalescing. | ||||||||||||
4321 | */ | ||||||||||||
4322 | static __isl_give isl_basic_map *coalesce_or_drop_more_redundant_divs( | ||||||||||||
4323 | __isl_take isl_basic_map *bmap, int *pairs, int n) | ||||||||||||
4324 | { | ||||||||||||
4325 | int i, l, u; | ||||||||||||
4326 | unsigned dim; | ||||||||||||
4327 | |||||||||||||
4328 | dim = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
4329 | |||||||||||||
4330 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
4331 | if (!pairs[i]) | ||||||||||||
4332 | continue; | ||||||||||||
4333 | for (l = 0; l < bmap->n_ineq; ++l) { | ||||||||||||
4334 | if (!isl_int_is_one(bmap->ineq[l][1 + dim + i])(isl_sioimath_cmp_si(*(bmap->ineq[l][1 + dim + i]), 1) == 0 )) | ||||||||||||
4335 | continue; | ||||||||||||
4336 | for (u = 0; u < bmap->n_ineq; ++u) { | ||||||||||||
4337 | int c; | ||||||||||||
4338 | |||||||||||||
4339 | if (!isl_int_is_negone(bmap->ineq[u][1+dim+i])(isl_sioimath_cmp_si(*(bmap->ineq[u][1+dim+i]), -1) == 0)) | ||||||||||||
4340 | continue; | ||||||||||||
4341 | c = div_find_coalesce(bmap, pairs, i, l, u); | ||||||||||||
4342 | if (c < 0) | ||||||||||||
4343 | continue; | ||||||||||||
4344 | free(pairs); | ||||||||||||
4345 | bmap = coalesce_divs(bmap, i, c, l, u); | ||||||||||||
4346 | return isl_basic_map_drop_redundant_divs(bmap); | ||||||||||||
4347 | } | ||||||||||||
4348 | } | ||||||||||||
4349 | } | ||||||||||||
4350 | |||||||||||||
4351 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)(!!(((bmap)->flags) & ((1 << 1))))) { | ||||||||||||
4352 | free(pairs); | ||||||||||||
4353 | return bmap; | ||||||||||||
4354 | } | ||||||||||||
4355 | |||||||||||||
4356 | return drop_more_redundant_divs(bmap, pairs, n); | ||||||||||||
4357 | } | ||||||||||||
4358 | |||||||||||||
4359 | /* Are the "n" coefficients starting at "first" of inequality constraints | ||||||||||||
4360 | * "i" and "j" of "bmap" equal to each other? | ||||||||||||
4361 | */ | ||||||||||||
4362 | static int is_parallel_part(__isl_keep isl_basic_map *bmap, int i, int j, | ||||||||||||
4363 | int first, int n) | ||||||||||||
4364 | { | ||||||||||||
4365 | return isl_seq_eq(bmap->ineq[i] + first, bmap->ineq[j] + first, n); | ||||||||||||
4366 | } | ||||||||||||
4367 | |||||||||||||
4368 | /* Are the "n" coefficients starting at "first" of inequality constraints | ||||||||||||
4369 | * "i" and "j" of "bmap" opposite to each other? | ||||||||||||
4370 | */ | ||||||||||||
4371 | static int is_opposite_part(__isl_keep isl_basic_map *bmap, int i, int j, | ||||||||||||
4372 | int first, int n) | ||||||||||||
4373 | { | ||||||||||||
4374 | return isl_seq_is_neg(bmap->ineq[i] + first, bmap->ineq[j] + first, n); | ||||||||||||
4375 | } | ||||||||||||
4376 | |||||||||||||
4377 | /* Are inequality constraints "i" and "j" of "bmap" opposite to each other, | ||||||||||||
4378 | * apart from the constant term? | ||||||||||||
4379 | */ | ||||||||||||
4380 | static isl_bool is_opposite(__isl_keep isl_basic_map *bmap, int i, int j) | ||||||||||||
4381 | { | ||||||||||||
4382 | unsigned total; | ||||||||||||
4383 | |||||||||||||
4384 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
4385 | return is_opposite_part(bmap, i, j, 1, total); | ||||||||||||
4386 | } | ||||||||||||
4387 | |||||||||||||
4388 | /* Are inequality constraints "i" and "j" of "bmap" equal to each other, | ||||||||||||
4389 | * apart from the constant term and the coefficient at position "pos"? | ||||||||||||
4390 | */ | ||||||||||||
4391 | static int is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j, | ||||||||||||
4392 | int pos) | ||||||||||||
4393 | { | ||||||||||||
4394 | unsigned total; | ||||||||||||
4395 | |||||||||||||
4396 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
4397 | return is_parallel_part(bmap, i, j, 1, pos - 1) && | ||||||||||||
4398 | is_parallel_part(bmap, i, j, pos + 1, total - pos); | ||||||||||||
4399 | } | ||||||||||||
4400 | |||||||||||||
4401 | /* Are inequality constraints "i" and "j" of "bmap" opposite to each other, | ||||||||||||
4402 | * apart from the constant term and the coefficient at position "pos"? | ||||||||||||
4403 | */ | ||||||||||||
4404 | static int is_opposite_except(__isl_keep isl_basic_map *bmap, int i, int j, | ||||||||||||
4405 | int pos) | ||||||||||||
4406 | { | ||||||||||||
4407 | unsigned total; | ||||||||||||
4408 | |||||||||||||
4409 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
4410 | return is_opposite_part(bmap, i, j, 1, pos - 1) && | ||||||||||||
4411 | is_opposite_part(bmap, i, j, pos + 1, total - pos); | ||||||||||||
4412 | } | ||||||||||||
4413 | |||||||||||||
4414 | /* Restart isl_basic_map_drop_redundant_divs after "bmap" has | ||||||||||||
4415 | * been modified, simplying it if "simplify" is set. | ||||||||||||
4416 | * Free the temporary data structure "pairs" that was associated | ||||||||||||
4417 | * to the old version of "bmap". | ||||||||||||
4418 | */ | ||||||||||||
4419 | static __isl_give isl_basic_map *drop_redundant_divs_again( | ||||||||||||
4420 | __isl_take isl_basic_map *bmap, __isl_take int *pairs, int simplify) | ||||||||||||
4421 | { | ||||||||||||
4422 | if (simplify) | ||||||||||||
4423 | bmap = isl_basic_map_simplify(bmap); | ||||||||||||
4424 | free(pairs); | ||||||||||||
4425 | return isl_basic_map_drop_redundant_divs(bmap); | ||||||||||||
4426 | } | ||||||||||||
4427 | |||||||||||||
4428 | /* Is "div" the single unknown existentially quantified variable | ||||||||||||
4429 | * in inequality constraint "ineq" of "bmap"? | ||||||||||||
4430 | * "div" is known to have a non-zero coefficient in "ineq". | ||||||||||||
4431 | */ | ||||||||||||
4432 | static isl_bool single_unknown(__isl_keep isl_basic_map *bmap, int ineq, | ||||||||||||
4433 | int div) | ||||||||||||
4434 | { | ||||||||||||
4435 | int i; | ||||||||||||
4436 | unsigned n_div, o_div; | ||||||||||||
4437 | isl_bool known; | ||||||||||||
4438 | |||||||||||||
4439 | known = isl_basic_map_div_is_known(bmap, div); | ||||||||||||
4440 | if (known < 0 || known) | ||||||||||||
4441 | return isl_bool_not(known); | ||||||||||||
4442 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
4443 | if (n_div == 1) | ||||||||||||
4444 | return isl_bool_true; | ||||||||||||
4445 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4446 | for (i = 0; i < n_div; ++i) { | ||||||||||||
4447 | isl_bool known; | ||||||||||||
4448 | |||||||||||||
4449 | if (i == div) | ||||||||||||
4450 | continue; | ||||||||||||
4451 | if (isl_int_is_zero(bmap->ineq[ineq][o_div + i])(isl_sioimath_sgn(*(bmap->ineq[ineq][o_div + i])) == 0)) | ||||||||||||
4452 | continue; | ||||||||||||
4453 | known = isl_basic_map_div_is_known(bmap, i); | ||||||||||||
4454 | if (known < 0 || !known) | ||||||||||||
4455 | return known; | ||||||||||||
4456 | } | ||||||||||||
4457 | |||||||||||||
4458 | return isl_bool_true; | ||||||||||||
4459 | } | ||||||||||||
4460 | |||||||||||||
4461 | /* Does integer division "div" have coefficient 1 in inequality constraint | ||||||||||||
4462 | * "ineq" of "map"? | ||||||||||||
4463 | */ | ||||||||||||
4464 | static isl_bool has_coef_one(__isl_keep isl_basic_map *bmap, int div, int ineq) | ||||||||||||
4465 | { | ||||||||||||
4466 | unsigned o_div; | ||||||||||||
4467 | |||||||||||||
4468 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4469 | if (isl_int_is_one(bmap->ineq[ineq][o_div + div])(isl_sioimath_cmp_si(*(bmap->ineq[ineq][o_div + div]), 1) == 0)) | ||||||||||||
4470 | return isl_bool_true; | ||||||||||||
4471 | |||||||||||||
4472 | return isl_bool_false; | ||||||||||||
4473 | } | ||||||||||||
4474 | |||||||||||||
4475 | /* Turn inequality constraint "ineq" of "bmap" into an equality and | ||||||||||||
4476 | * then try and drop redundant divs again, | ||||||||||||
4477 | * freeing the temporary data structure "pairs" that was associated | ||||||||||||
4478 | * to the old version of "bmap". | ||||||||||||
4479 | */ | ||||||||||||
4480 | static __isl_give isl_basic_map *set_eq_and_try_again( | ||||||||||||
4481 | __isl_take isl_basic_map *bmap, int ineq, __isl_take int *pairs) | ||||||||||||
4482 | { | ||||||||||||
4483 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
4484 | isl_basic_map_inequality_to_equality(bmap, ineq); | ||||||||||||
4485 | return drop_redundant_divs_again(bmap, pairs, 1); | ||||||||||||
4486 | } | ||||||||||||
4487 | |||||||||||||
4488 | /* Drop the integer division at position "div", along with the two | ||||||||||||
4489 | * inequality constraints "ineq1" and "ineq2" in which it appears | ||||||||||||
4490 | * from "bmap" and then try and drop redundant divs again, | ||||||||||||
4491 | * freeing the temporary data structure "pairs" that was associated | ||||||||||||
4492 | * to the old version of "bmap". | ||||||||||||
4493 | */ | ||||||||||||
4494 | static __isl_give isl_basic_map *drop_div_and_try_again( | ||||||||||||
4495 | __isl_take isl_basic_map *bmap, int div, int ineq1, int ineq2, | ||||||||||||
4496 | __isl_take int *pairs) | ||||||||||||
4497 | { | ||||||||||||
4498 | if (ineq1 > ineq2) { | ||||||||||||
4499 | isl_basic_map_drop_inequality(bmap, ineq1); | ||||||||||||
4500 | isl_basic_map_drop_inequality(bmap, ineq2); | ||||||||||||
4501 | } else { | ||||||||||||
4502 | isl_basic_map_drop_inequality(bmap, ineq2); | ||||||||||||
4503 | isl_basic_map_drop_inequality(bmap, ineq1); | ||||||||||||
4504 | } | ||||||||||||
4505 | bmap = isl_basic_map_drop_div(bmap, div); | ||||||||||||
4506 | return drop_redundant_divs_again(bmap, pairs, 0); | ||||||||||||
4507 | } | ||||||||||||
4508 | |||||||||||||
4509 | /* Given two inequality constraints | ||||||||||||
4510 | * | ||||||||||||
4511 | * f(x) + n d + c >= 0, (ineq) | ||||||||||||
4512 | * | ||||||||||||
4513 | * with d the variable at position "pos", and | ||||||||||||
4514 | * | ||||||||||||
4515 | * f(x) + c0 >= 0, (lower) | ||||||||||||
4516 | * | ||||||||||||
4517 | * compute the maximal value of the lower bound ceil((-f(x) - c)/n) | ||||||||||||
4518 | * determined by the first constraint. | ||||||||||||
4519 | * That is, store | ||||||||||||
4520 | * | ||||||||||||
4521 | * ceil((c0 - c)/n) | ||||||||||||
4522 | * | ||||||||||||
4523 | * in *l. | ||||||||||||
4524 | */ | ||||||||||||
4525 | static void lower_bound_from_parallel(__isl_keep isl_basic_map *bmap, | ||||||||||||
4526 | int ineq, int lower, int pos, isl_int *l) | ||||||||||||
4527 | { | ||||||||||||
4528 | isl_int_neg(*l, bmap->ineq[ineq][0])isl_sioimath_neg((*l), *(bmap->ineq[ineq][0])); | ||||||||||||
4529 | isl_int_add(*l, *l, bmap->ineq[lower][0])isl_sioimath_add((*l), *(*l), *(bmap->ineq[lower][0])); | ||||||||||||
4530 | isl_int_cdiv_q(*l, *l, bmap->ineq[ineq][pos])isl_sioimath_cdiv_q((*l), *(*l), *(bmap->ineq[ineq][pos])); | ||||||||||||
4531 | } | ||||||||||||
4532 | |||||||||||||
4533 | /* Given two inequality constraints | ||||||||||||
4534 | * | ||||||||||||
4535 | * f(x) + n d + c >= 0, (ineq) | ||||||||||||
4536 | * | ||||||||||||
4537 | * with d the variable at position "pos", and | ||||||||||||
4538 | * | ||||||||||||
4539 | * -f(x) - c0 >= 0, (upper) | ||||||||||||
4540 | * | ||||||||||||
4541 | * compute the minimal value of the lower bound ceil((-f(x) - c)/n) | ||||||||||||
4542 | * determined by the first constraint. | ||||||||||||
4543 | * That is, store | ||||||||||||
4544 | * | ||||||||||||
4545 | * ceil((-c1 - c)/n) | ||||||||||||
4546 | * | ||||||||||||
4547 | * in *u. | ||||||||||||
4548 | */ | ||||||||||||
4549 | static void lower_bound_from_opposite(__isl_keep isl_basic_map *bmap, | ||||||||||||
4550 | int ineq, int upper, int pos, isl_int *u) | ||||||||||||
4551 | { | ||||||||||||
4552 | isl_int_neg(*u, bmap->ineq[ineq][0])isl_sioimath_neg((*u), *(bmap->ineq[ineq][0])); | ||||||||||||
4553 | isl_int_sub(*u, *u, bmap->ineq[upper][0])isl_sioimath_sub((*u), *(*u), *(bmap->ineq[upper][0])); | ||||||||||||
4554 | isl_int_cdiv_q(*u, *u, bmap->ineq[ineq][pos])isl_sioimath_cdiv_q((*u), *(*u), *(bmap->ineq[ineq][pos])); | ||||||||||||
4555 | } | ||||||||||||
4556 | |||||||||||||
4557 | /* Given a lower bound constraint "ineq" on "div" in "bmap", | ||||||||||||
4558 | * does the corresponding lower bound have a fixed value in "bmap"? | ||||||||||||
4559 | * | ||||||||||||
4560 | * In particular, "ineq" is of the form | ||||||||||||
4561 | * | ||||||||||||
4562 | * f(x) + n d + c >= 0 | ||||||||||||
4563 | * | ||||||||||||
4564 | * with n > 0, c the constant term and | ||||||||||||
4565 | * d the existentially quantified variable "div". | ||||||||||||
4566 | * That is, the lower bound is | ||||||||||||
4567 | * | ||||||||||||
4568 | * ceil((-f(x) - c)/n) | ||||||||||||
4569 | * | ||||||||||||
4570 | * Look for a pair of constraints | ||||||||||||
4571 | * | ||||||||||||
4572 | * f(x) + c0 >= 0 | ||||||||||||
4573 | * -f(x) + c1 >= 0 | ||||||||||||
4574 | * | ||||||||||||
4575 | * i.e., -c1 <= -f(x) <= c0, that fix ceil((-f(x) - c)/n) to a constant value. | ||||||||||||
4576 | * That is, check that | ||||||||||||
4577 | * | ||||||||||||
4578 | * ceil((-c1 - c)/n) = ceil((c0 - c)/n) | ||||||||||||
4579 | * | ||||||||||||
4580 | * If so, return the index of inequality f(x) + c0 >= 0. | ||||||||||||
4581 | * Otherwise, return -1. | ||||||||||||
4582 | */ | ||||||||||||
4583 | static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq) | ||||||||||||
4584 | { | ||||||||||||
4585 | int i; | ||||||||||||
4586 | int lower = -1, upper = -1; | ||||||||||||
4587 | unsigned o_div; | ||||||||||||
4588 | isl_int l, u; | ||||||||||||
4589 | int equal; | ||||||||||||
4590 | |||||||||||||
4591 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4592 | for (i = 0; i < bmap->n_ineq && (lower < 0 || upper < 0); ++i) { | ||||||||||||
4593 | if (i == ineq) | ||||||||||||
4594 | continue; | ||||||||||||
4595 | if (!isl_int_is_zero(bmap->ineq[i][o_div + div])(isl_sioimath_sgn(*(bmap->ineq[i][o_div + div])) == 0)) | ||||||||||||
4596 | continue; | ||||||||||||
4597 | if (lower < 0 && | ||||||||||||
4598 | is_parallel_except(bmap, ineq, i, o_div + div)) { | ||||||||||||
4599 | lower = i; | ||||||||||||
4600 | continue; | ||||||||||||
4601 | } | ||||||||||||
4602 | if (upper < 0 && | ||||||||||||
4603 | is_opposite_except(bmap, ineq, i, o_div + div)) { | ||||||||||||
4604 | upper = i; | ||||||||||||
4605 | } | ||||||||||||
4606 | } | ||||||||||||
4607 | |||||||||||||
4608 | if (lower < 0 || upper < 0) | ||||||||||||
4609 | return -1; | ||||||||||||
4610 | |||||||||||||
4611 | isl_int_init(l)isl_sioimath_init((l)); | ||||||||||||
4612 | isl_int_init(u)isl_sioimath_init((u)); | ||||||||||||
4613 | |||||||||||||
4614 | lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &l); | ||||||||||||
4615 | lower_bound_from_opposite(bmap, ineq, upper, o_div + div, &u); | ||||||||||||
4616 | |||||||||||||
4617 | equal = isl_int_eq(l, u)(isl_sioimath_cmp(*(l), *(u)) == 0); | ||||||||||||
4618 | |||||||||||||
4619 | isl_int_clear(l)isl_sioimath_clear((l)); | ||||||||||||
4620 | isl_int_clear(u)isl_sioimath_clear((u)); | ||||||||||||
4621 | |||||||||||||
4622 | return equal ? lower : -1; | ||||||||||||
4623 | } | ||||||||||||
4624 | |||||||||||||
4625 | /* Given a lower bound constraint "ineq" on the existentially quantified | ||||||||||||
4626 | * variable "div", such that the corresponding lower bound has | ||||||||||||
4627 | * a fixed value in "bmap", assign this fixed value to the variable and | ||||||||||||
4628 | * then try and drop redundant divs again, | ||||||||||||
4629 | * freeing the temporary data structure "pairs" that was associated | ||||||||||||
4630 | * to the old version of "bmap". | ||||||||||||
4631 | * "lower" determines the constant value for the lower bound. | ||||||||||||
4632 | * | ||||||||||||
4633 | * In particular, "ineq" is of the form | ||||||||||||
4634 | * | ||||||||||||
4635 | * f(x) + n d + c >= 0, | ||||||||||||
4636 | * | ||||||||||||
4637 | * while "lower" is of the form | ||||||||||||
4638 | * | ||||||||||||
4639 | * f(x) + c0 >= 0 | ||||||||||||
4640 | * | ||||||||||||
4641 | * The lower bound is ceil((-f(x) - c)/n) and its constant value | ||||||||||||
4642 | * is ceil((c0 - c)/n). | ||||||||||||
4643 | */ | ||||||||||||
4644 | static __isl_give isl_basic_map *fix_cst_lower(__isl_take isl_basic_map *bmap, | ||||||||||||
4645 | int div, int ineq, int lower, int *pairs) | ||||||||||||
4646 | { | ||||||||||||
4647 | isl_int c; | ||||||||||||
4648 | unsigned o_div; | ||||||||||||
4649 | |||||||||||||
4650 | isl_int_init(c)isl_sioimath_init((c)); | ||||||||||||
4651 | |||||||||||||
4652 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4653 | lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &c); | ||||||||||||
4654 | bmap = isl_basic_map_fix(bmap, isl_dim_div, div, c); | ||||||||||||
4655 | free(pairs); | ||||||||||||
4656 | |||||||||||||
4657 | isl_int_clear(c)isl_sioimath_clear((c)); | ||||||||||||
4658 | |||||||||||||
4659 | return isl_basic_map_drop_redundant_divs(bmap); | ||||||||||||
4660 | } | ||||||||||||
4661 | |||||||||||||
4662 | /* Remove divs that are not strictly needed based on the inequality | ||||||||||||
4663 | * constraints. | ||||||||||||
4664 | * In particular, if a div only occurs positively (or negatively) | ||||||||||||
4665 | * in constraints, then it can simply be dropped. | ||||||||||||
4666 | * Also, if a div occurs in only two constraints and if moreover | ||||||||||||
4667 | * those two constraints are opposite to each other, except for the constant | ||||||||||||
4668 | * term and if the sum of the constant terms is such that for any value | ||||||||||||
4669 | * of the other values, there is always at least one integer value of the | ||||||||||||
4670 | * div, i.e., if one plus this sum is greater than or equal to | ||||||||||||
4671 | * the (absolute value) of the coefficient of the div in the constraints, | ||||||||||||
4672 | * then we can also simply drop the div. | ||||||||||||
4673 | * | ||||||||||||
4674 | * If an existentially quantified variable does not have an explicit | ||||||||||||
4675 | * representation, appears in only a single lower bound that does not | ||||||||||||
4676 | * involve any other such existentially quantified variables and appears | ||||||||||||
4677 | * in this lower bound with coefficient 1, | ||||||||||||
4678 | * then fix the variable to the value of the lower bound. That is, | ||||||||||||
4679 | * turn the inequality into an equality. | ||||||||||||
4680 | * If for any value of the other variables, there is any value | ||||||||||||
4681 | * for the existentially quantified variable satisfying the constraints, | ||||||||||||
4682 | * then this lower bound also satisfies the constraints. | ||||||||||||
4683 | * It is therefore safe to pick this lower bound. | ||||||||||||
4684 | * | ||||||||||||
4685 | * The same reasoning holds even if the coefficient is not one. | ||||||||||||
4686 | * However, fixing the variable to the value of the lower bound may | ||||||||||||
4687 | * in general introduce an extra integer division, in which case | ||||||||||||
4688 | * it may be better to pick another value. | ||||||||||||
4689 | * If this integer division has a known constant value, then plugging | ||||||||||||
4690 | * in this constant value removes the existentially quantified variable | ||||||||||||
4691 | * completely. In particular, if the lower bound is of the form | ||||||||||||
4692 | * ceil((-f(x) - c)/n) and there are two constraints, f(x) + c0 >= 0 and | ||||||||||||
4693 | * -f(x) + c1 >= 0 such that ceil((-c1 - c)/n) = ceil((c0 - c)/n), | ||||||||||||
4694 | * then the existentially quantified variable can be assigned this | ||||||||||||
4695 | * shared value. | ||||||||||||
4696 | * | ||||||||||||
4697 | * We skip divs that appear in equalities or in the definition of other divs. | ||||||||||||
4698 | * Divs that appear in the definition of other divs usually occur in at least | ||||||||||||
4699 | * 4 constraints, but the constraints may have been simplified. | ||||||||||||
4700 | * | ||||||||||||
4701 | * If any divs are left after these simple checks then we move on | ||||||||||||
4702 | * to more complicated cases in drop_more_redundant_divs. | ||||||||||||
4703 | */ | ||||||||||||
4704 | static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq( | ||||||||||||
4705 | __isl_take isl_basic_map *bmap) | ||||||||||||
4706 | { | ||||||||||||
4707 | int i, j; | ||||||||||||
4708 | unsigned off; | ||||||||||||
4709 | int *pairs = NULL((void*)0); | ||||||||||||
4710 | int n = 0; | ||||||||||||
4711 | |||||||||||||
4712 | if (!bmap) | ||||||||||||
4713 | goto error; | ||||||||||||
4714 | if (bmap->n_div == 0) | ||||||||||||
4715 | return bmap; | ||||||||||||
4716 | |||||||||||||
4717 | off = isl_space_dim(bmap->dim, isl_dim_all); | ||||||||||||
4718 | pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div)((int *)isl_calloc_or_die(bmap->ctx, bmap->n_div, sizeof (int))); | ||||||||||||
4719 | if (!pairs) | ||||||||||||
4720 | goto error; | ||||||||||||
4721 | |||||||||||||
4722 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
4723 | int pos, neg; | ||||||||||||
4724 | int last_pos, last_neg; | ||||||||||||
4725 | int redundant; | ||||||||||||
4726 | int defined; | ||||||||||||
4727 | isl_bool opp, set_div; | ||||||||||||
4728 | |||||||||||||
4729 | defined = !isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0); | ||||||||||||
4730 | for (j = i; j < bmap->n_div; ++j) | ||||||||||||
4731 | if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i])(isl_sioimath_sgn(*(bmap->div[j][1 + 1 + off + i])) == 0)) | ||||||||||||
4732 | break; | ||||||||||||
4733 | if (j < bmap->n_div) | ||||||||||||
4734 | continue; | ||||||||||||
4735 | for (j = 0; j < bmap->n_eq; ++j) | ||||||||||||
4736 | if (!isl_int_is_zero(bmap->eq[j][1 + off + i])(isl_sioimath_sgn(*(bmap->eq[j][1 + off + i])) == 0)) | ||||||||||||
4737 | break; | ||||||||||||
4738 | if (j < bmap->n_eq) | ||||||||||||
4739 | continue; | ||||||||||||
4740 | ++n; | ||||||||||||
4741 | pos = neg = 0; | ||||||||||||
4742 | for (j = 0; j < bmap->n_ineq; ++j) { | ||||||||||||
4743 | if (isl_int_is_pos(bmap->ineq[j][1 + off + i])(isl_sioimath_sgn(*(bmap->ineq[j][1 + off + i])) > 0)) { | ||||||||||||
4744 | last_pos = j; | ||||||||||||
4745 | ++pos; | ||||||||||||
4746 | } | ||||||||||||
4747 | if (isl_int_is_neg(bmap->ineq[j][1 + off + i])(isl_sioimath_sgn(*(bmap->ineq[j][1 + off + i])) < 0)) { | ||||||||||||
4748 | last_neg = j; | ||||||||||||
4749 | ++neg; | ||||||||||||
4750 | } | ||||||||||||
4751 | } | ||||||||||||
4752 | pairs[i] = pos * neg; | ||||||||||||
4753 | if (pairs[i] == 0) { | ||||||||||||
4754 | for (j = bmap->n_ineq - 1; j >= 0; --j) | ||||||||||||
4755 | if (!isl_int_is_zero(bmap->ineq[j][1+off+i])(isl_sioimath_sgn(*(bmap->ineq[j][1+off+i])) == 0)) | ||||||||||||
4756 | isl_basic_map_drop_inequality(bmap, j); | ||||||||||||
4757 | bmap = isl_basic_map_drop_div(bmap, i); | ||||||||||||
4758 | return drop_redundant_divs_again(bmap, pairs, 0); | ||||||||||||
4759 | } | ||||||||||||
4760 | if (pairs[i] != 1) | ||||||||||||
4761 | opp = isl_bool_false; | ||||||||||||
4762 | else | ||||||||||||
4763 | opp = is_opposite(bmap, last_pos, last_neg); | ||||||||||||
4764 | if (opp < 0) | ||||||||||||
4765 | goto error; | ||||||||||||
4766 | if (!opp) { | ||||||||||||
4767 | int lower; | ||||||||||||
4768 | isl_bool single, one; | ||||||||||||
4769 | |||||||||||||
4770 | if (pos != 1) | ||||||||||||
4771 | continue; | ||||||||||||
4772 | single = single_unknown(bmap, last_pos, i); | ||||||||||||
4773 | if (single < 0) | ||||||||||||
4774 | goto error; | ||||||||||||
4775 | if (!single) | ||||||||||||
4776 | continue; | ||||||||||||
4777 | one = has_coef_one(bmap, i, last_pos); | ||||||||||||
4778 | if (one < 0) | ||||||||||||
4779 | goto error; | ||||||||||||
4780 | if (one) | ||||||||||||
4781 | return set_eq_and_try_again(bmap, last_pos, | ||||||||||||
4782 | pairs); | ||||||||||||
4783 | lower = lower_bound_is_cst(bmap, i, last_pos); | ||||||||||||
4784 | if (lower >= 0) | ||||||||||||
4785 | return fix_cst_lower(bmap, i, last_pos, lower, | ||||||||||||
4786 | pairs); | ||||||||||||
4787 | continue; | ||||||||||||
4788 | } | ||||||||||||
4789 | |||||||||||||
4790 | isl_int_add(bmap->ineq[last_pos][0],isl_sioimath_add((bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][0]), *(bmap->ineq[last_neg][0])) | ||||||||||||
4791 | bmap->ineq[last_pos][0], bmap->ineq[last_neg][0])isl_sioimath_add((bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][0]), *(bmap->ineq[last_neg][0])); | ||||||||||||
4792 | isl_int_add_ui(bmap->ineq[last_pos][0],isl_sioimath_add_ui((bmap->ineq[last_pos][0]), *(bmap-> ineq[last_pos][0]), 1) | ||||||||||||
4793 | bmap->ineq[last_pos][0], 1)isl_sioimath_add_ui((bmap->ineq[last_pos][0]), *(bmap-> ineq[last_pos][0]), 1); | ||||||||||||
4794 | redundant = isl_int_ge(bmap->ineq[last_pos][0],(isl_sioimath_cmp(*(bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][1+off+i])) >= 0) | ||||||||||||
4795 | bmap->ineq[last_pos][1+off+i])(isl_sioimath_cmp(*(bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][1+off+i])) >= 0); | ||||||||||||
4796 | isl_int_sub_ui(bmap->ineq[last_pos][0],isl_sioimath_sub_ui((bmap->ineq[last_pos][0]), *(bmap-> ineq[last_pos][0]), 1) | ||||||||||||
4797 | bmap->ineq[last_pos][0], 1)isl_sioimath_sub_ui((bmap->ineq[last_pos][0]), *(bmap-> ineq[last_pos][0]), 1); | ||||||||||||
4798 | isl_int_sub(bmap->ineq[last_pos][0],isl_sioimath_sub((bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][0]), *(bmap->ineq[last_neg][0])) | ||||||||||||
4799 | bmap->ineq[last_pos][0], bmap->ineq[last_neg][0])isl_sioimath_sub((bmap->ineq[last_pos][0]), *(bmap->ineq [last_pos][0]), *(bmap->ineq[last_neg][0])); | ||||||||||||
4800 | if (redundant) | ||||||||||||
4801 | return drop_div_and_try_again(bmap, i, | ||||||||||||
4802 | last_pos, last_neg, pairs); | ||||||||||||
4803 | if (defined) | ||||||||||||
4804 | set_div = isl_bool_false; | ||||||||||||
4805 | else | ||||||||||||
4806 | set_div = ok_to_set_div_from_bound(bmap, i, last_pos); | ||||||||||||
4807 | if (set_div < 0) | ||||||||||||
4808 | return isl_basic_map_free(bmap); | ||||||||||||
4809 | if (set_div) { | ||||||||||||
4810 | bmap = set_div_from_lower_bound(bmap, i, last_pos); | ||||||||||||
4811 | return drop_redundant_divs_again(bmap, pairs, 1); | ||||||||||||
4812 | } | ||||||||||||
4813 | pairs[i] = 0; | ||||||||||||
4814 | --n; | ||||||||||||
4815 | } | ||||||||||||
4816 | |||||||||||||
4817 | if (n > 0) | ||||||||||||
4818 | return coalesce_or_drop_more_redundant_divs(bmap, pairs, n); | ||||||||||||
4819 | |||||||||||||
4820 | free(pairs); | ||||||||||||
4821 | return bmap; | ||||||||||||
4822 | error: | ||||||||||||
4823 | free(pairs); | ||||||||||||
4824 | isl_basic_map_free(bmap); | ||||||||||||
4825 | return NULL((void*)0); | ||||||||||||
4826 | } | ||||||||||||
4827 | |||||||||||||
4828 | /* Consider the coefficients at "c" as a row vector and replace | ||||||||||||
4829 | * them with their product with "T". "T" is assumed to be a square matrix. | ||||||||||||
4830 | */ | ||||||||||||
4831 | static isl_stat preimage(isl_int *c, __isl_keep isl_mat *T) | ||||||||||||
4832 | { | ||||||||||||
4833 | int n; | ||||||||||||
4834 | isl_ctx *ctx; | ||||||||||||
4835 | isl_vec *v; | ||||||||||||
4836 | |||||||||||||
4837 | if (!T) | ||||||||||||
4838 | return isl_stat_error; | ||||||||||||
4839 | n = isl_mat_rows(T); | ||||||||||||
4840 | if (isl_seq_first_non_zero(c, n) == -1) | ||||||||||||
4841 | return isl_stat_ok; | ||||||||||||
4842 | ctx = isl_mat_get_ctx(T); | ||||||||||||
4843 | v = isl_vec_alloc(ctx, n); | ||||||||||||
4844 | if (!v) | ||||||||||||
4845 | return isl_stat_error; | ||||||||||||
4846 | isl_seq_swp_or_cpy(v->el, c, n); | ||||||||||||
4847 | v = isl_vec_mat_product(v, isl_mat_copy(T)); | ||||||||||||
4848 | if (!v) | ||||||||||||
4849 | return isl_stat_error; | ||||||||||||
4850 | isl_seq_swp_or_cpy(c, v->el, n); | ||||||||||||
4851 | isl_vec_free(v); | ||||||||||||
4852 | |||||||||||||
4853 | return isl_stat_ok; | ||||||||||||
4854 | } | ||||||||||||
4855 | |||||||||||||
4856 | /* Plug in T for the variables in "bmap" starting at "pos". | ||||||||||||
4857 | * T is a linear unimodular matrix, i.e., without constant term. | ||||||||||||
4858 | */ | ||||||||||||
4859 | static __isl_give isl_basic_map *isl_basic_map_preimage_vars( | ||||||||||||
4860 | __isl_take isl_basic_map *bmap, unsigned pos, __isl_take isl_mat *T) | ||||||||||||
4861 | { | ||||||||||||
4862 | int i; | ||||||||||||
4863 | unsigned n, total; | ||||||||||||
4864 | |||||||||||||
4865 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
4866 | if (!bmap || !T) | ||||||||||||
4867 | goto error; | ||||||||||||
4868 | |||||||||||||
4869 | n = isl_mat_cols(T); | ||||||||||||
4870 | if (n != isl_mat_rows(T)) | ||||||||||||
4871 | isl_die(isl_mat_get_ctx(T), isl_error_invalid,do { isl_handle_error(isl_mat_get_ctx(T), isl_error_invalid, "expecting square matrix" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 4872); goto error; } while (0) | ||||||||||||
4872 | "expecting square matrix", goto error)do { isl_handle_error(isl_mat_get_ctx(T), isl_error_invalid, "expecting square matrix" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 4872); goto error; } while (0); | ||||||||||||
4873 | |||||||||||||
4874 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
4875 | if (pos + n > total || pos + n < pos) | ||||||||||||
4876 | isl_die(isl_mat_get_ctx(T), isl_error_invalid,do { isl_handle_error(isl_mat_get_ctx(T), isl_error_invalid, "invalid range" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 4877); goto error; } while (0) | ||||||||||||
4877 | "invalid range", goto error)do { isl_handle_error(isl_mat_get_ctx(T), isl_error_invalid, "invalid range" , "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/polly/lib/External/isl/isl_map_simplify.c" , 4877); goto error; } while (0); | ||||||||||||
4878 | |||||||||||||
4879 | for (i = 0; i < bmap->n_eq; ++i) | ||||||||||||
4880 | if (preimage(bmap->eq[i] + 1 + pos, T) < 0) | ||||||||||||
4881 | goto error; | ||||||||||||
4882 | for (i = 0; i < bmap->n_ineq; ++i) | ||||||||||||
4883 | if (preimage(bmap->ineq[i] + 1 + pos, T) < 0) | ||||||||||||
4884 | goto error; | ||||||||||||
4885 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
4886 | if (isl_basic_map_div_is_marked_unknown(bmap, i)) | ||||||||||||
4887 | continue; | ||||||||||||
4888 | if (preimage(bmap->div[i] + 1 + 1 + pos, T) < 0) | ||||||||||||
4889 | goto error; | ||||||||||||
4890 | } | ||||||||||||
4891 | |||||||||||||
4892 | isl_mat_free(T); | ||||||||||||
4893 | return bmap; | ||||||||||||
4894 | error: | ||||||||||||
4895 | isl_basic_map_free(bmap); | ||||||||||||
4896 | isl_mat_free(T); | ||||||||||||
4897 | return NULL((void*)0); | ||||||||||||
4898 | } | ||||||||||||
4899 | |||||||||||||
4900 | /* Remove divs that are not strictly needed. | ||||||||||||
4901 | * | ||||||||||||
4902 | * First look for an equality constraint involving two or more | ||||||||||||
4903 | * existentially quantified variables without an explicit | ||||||||||||
4904 | * representation. Replace the combination that appears | ||||||||||||
4905 | * in the equality constraint by a single existentially quantified | ||||||||||||
4906 | * variable such that the equality can be used to derive | ||||||||||||
4907 | * an explicit representation for the variable. | ||||||||||||
4908 | * If there are no more such equality constraints, then continue | ||||||||||||
4909 | * with isl_basic_map_drop_redundant_divs_ineq. | ||||||||||||
4910 | * | ||||||||||||
4911 | * In particular, if the equality constraint is of the form | ||||||||||||
4912 | * | ||||||||||||
4913 | * f(x) + \sum_i c_i a_i = 0 | ||||||||||||
4914 | * | ||||||||||||
4915 | * with a_i existentially quantified variable without explicit | ||||||||||||
4916 | * representation, then apply a transformation on the existentially | ||||||||||||
4917 | * quantified variables to turn the constraint into | ||||||||||||
4918 | * | ||||||||||||
4919 | * f(x) + g a_1' = 0 | ||||||||||||
4920 | * | ||||||||||||
4921 | * with g the gcd of the c_i. | ||||||||||||
4922 | * In order to easily identify which existentially quantified variables | ||||||||||||
4923 | * have a complete explicit representation, i.e., without being defined | ||||||||||||
4924 | * in terms of other existentially quantified variables without | ||||||||||||
4925 | * an explicit representation, the existentially quantified variables | ||||||||||||
4926 | * are first sorted. | ||||||||||||
4927 | * | ||||||||||||
4928 | * The variable transformation is computed by extending the row | ||||||||||||
4929 | * [c_1/g ... c_n/g] to a unimodular matrix, obtaining the transformation | ||||||||||||
4930 | * | ||||||||||||
4931 | * [a_1'] [c_1/g ... c_n/g] [ a_1 ] | ||||||||||||
4932 | * [a_2'] [ a_2 ] | ||||||||||||
4933 | * ... = U .... | ||||||||||||
4934 | * [a_n'] [ a_n ] | ||||||||||||
4935 | * | ||||||||||||
4936 | * with [c_1/g ... c_n/g] representing the first row of U. | ||||||||||||
4937 | * The inverse of U is then plugged into the original constraints. | ||||||||||||
4938 | * The call to isl_basic_map_simplify makes sure the explicit | ||||||||||||
4939 | * representation for a_1' is extracted from the equality constraint. | ||||||||||||
4940 | */ | ||||||||||||
4941 | __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs( | ||||||||||||
4942 | __isl_take isl_basic_map *bmap) | ||||||||||||
4943 | { | ||||||||||||
4944 | int first; | ||||||||||||
4945 | int i; | ||||||||||||
4946 | unsigned o_div, n_div; | ||||||||||||
4947 | int l; | ||||||||||||
4948 | isl_ctx *ctx; | ||||||||||||
4949 | isl_mat *T; | ||||||||||||
4950 | |||||||||||||
4951 | if (!bmap) | ||||||||||||
4952 | return NULL((void*)0); | ||||||||||||
4953 | if (isl_basic_map_divs_known(bmap)) | ||||||||||||
4954 | return isl_basic_map_drop_redundant_divs_ineq(bmap); | ||||||||||||
4955 | if (bmap->n_eq == 0) | ||||||||||||
4956 | return isl_basic_map_drop_redundant_divs_ineq(bmap); | ||||||||||||
4957 | bmap = isl_basic_map_sort_divs(bmap); | ||||||||||||
4958 | if (!bmap) | ||||||||||||
4959 | return NULL((void*)0); | ||||||||||||
4960 | |||||||||||||
4961 | first = isl_basic_map_first_unknown_div(bmap); | ||||||||||||
4962 | if (first < 0) | ||||||||||||
4963 | return isl_basic_map_free(bmap); | ||||||||||||
4964 | |||||||||||||
4965 | o_div = isl_basic_map_offset(bmap, isl_dim_div); | ||||||||||||
4966 | n_div = isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
4967 | |||||||||||||
4968 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
4969 | l = isl_seq_first_non_zero(bmap->eq[i] + o_div + first, | ||||||||||||
4970 | n_div - (first)); | ||||||||||||
4971 | if (l < 0) | ||||||||||||
4972 | continue; | ||||||||||||
4973 | l += first; | ||||||||||||
4974 | if (isl_seq_first_non_zero(bmap->eq[i] + o_div + l + 1, | ||||||||||||
4975 | n_div - (l + 1)) == -1) | ||||||||||||
4976 | continue; | ||||||||||||
4977 | break; | ||||||||||||
4978 | } | ||||||||||||
4979 | if (i >= bmap->n_eq) | ||||||||||||
4980 | return isl_basic_map_drop_redundant_divs_ineq(bmap); | ||||||||||||
4981 | |||||||||||||
4982 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
4983 | T = isl_mat_alloc(ctx, n_div - l, n_div - l); | ||||||||||||
4984 | if (!T) | ||||||||||||
4985 | return isl_basic_map_free(bmap); | ||||||||||||
4986 | isl_seq_cpy(T->row[0], bmap->eq[i] + o_div + l, n_div - l); | ||||||||||||
4987 | T = isl_mat_normalize_row(T, 0); | ||||||||||||
4988 | T = isl_mat_unimodular_complete(T, 1); | ||||||||||||
4989 | T = isl_mat_right_inverse(T); | ||||||||||||
4990 | |||||||||||||
4991 | for (i = l; i < n_div; ++i) | ||||||||||||
4992 | bmap = isl_basic_map_mark_div_unknown(bmap, i); | ||||||||||||
4993 | bmap = isl_basic_map_preimage_vars(bmap, o_div - 1 + l, T); | ||||||||||||
4994 | bmap = isl_basic_map_simplify(bmap); | ||||||||||||
4995 | |||||||||||||
4996 | return isl_basic_map_drop_redundant_divs(bmap); | ||||||||||||
4997 | } | ||||||||||||
4998 | |||||||||||||
4999 | /* Does "bmap" satisfy any equality that involves more than 2 variables | ||||||||||||
5000 | * and/or has coefficients different from -1 and 1? | ||||||||||||
5001 | */ | ||||||||||||
5002 | static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap) | ||||||||||||
5003 | { | ||||||||||||
5004 | int i; | ||||||||||||
5005 | unsigned total; | ||||||||||||
5006 | |||||||||||||
5007 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
5008 | |||||||||||||
5009 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
5010 | int j, k; | ||||||||||||
5011 | |||||||||||||
5012 | j = isl_seq_first_non_zero(bmap->eq[i] + 1, total); | ||||||||||||
5013 | if (j < 0) | ||||||||||||
5014 | continue; | ||||||||||||
5015 | if (!isl_int_is_one(bmap->eq[i][1 + j])(isl_sioimath_cmp_si(*(bmap->eq[i][1 + j]), 1) == 0) && | ||||||||||||
5016 | !isl_int_is_negone(bmap->eq[i][1 + j])(isl_sioimath_cmp_si(*(bmap->eq[i][1 + j]), -1) == 0)) | ||||||||||||
5017 | return 1; | ||||||||||||
5018 | |||||||||||||
5019 | j += 1; | ||||||||||||
5020 | k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j); | ||||||||||||
5021 | if (k < 0) | ||||||||||||
5022 | continue; | ||||||||||||
5023 | j += k; | ||||||||||||
5024 | if (!isl_int_is_one(bmap->eq[i][1 + j])(isl_sioimath_cmp_si(*(bmap->eq[i][1 + j]), 1) == 0) && | ||||||||||||
5025 | !isl_int_is_negone(bmap->eq[i][1 + j])(isl_sioimath_cmp_si(*(bmap->eq[i][1 + j]), -1) == 0)) | ||||||||||||
5026 | return 1; | ||||||||||||
5027 | |||||||||||||
5028 | j += 1; | ||||||||||||
5029 | k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j); | ||||||||||||
5030 | if (k >= 0) | ||||||||||||
5031 | return 1; | ||||||||||||
5032 | } | ||||||||||||
5033 | |||||||||||||
5034 | return 0; | ||||||||||||
5035 | } | ||||||||||||
5036 | |||||||||||||
5037 | /* Remove any common factor g from the constraint coefficients in "v". | ||||||||||||
5038 | * The constant term is stored in the first position and is replaced | ||||||||||||
5039 | * by floor(c/g). If any common factor is removed and if this results | ||||||||||||
5040 | * in a tightening of the constraint, then set *tightened. | ||||||||||||
5041 | */ | ||||||||||||
5042 | static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v, | ||||||||||||
5043 | int *tightened) | ||||||||||||
5044 | { | ||||||||||||
5045 | isl_ctx *ctx; | ||||||||||||
5046 | |||||||||||||
5047 | if (!v) | ||||||||||||
5048 | return NULL((void*)0); | ||||||||||||
5049 | ctx = isl_vec_get_ctx(v); | ||||||||||||
5050 | isl_seq_gcd(v->el + 1, v->size - 1, &ctx->normalize_gcd); | ||||||||||||
5051 | if (isl_int_is_zero(ctx->normalize_gcd)(isl_sioimath_sgn(*(ctx->normalize_gcd)) == 0)) | ||||||||||||
5052 | return v; | ||||||||||||
5053 | if (isl_int_is_one(ctx->normalize_gcd)(isl_sioimath_cmp_si(*(ctx->normalize_gcd), 1) == 0)) | ||||||||||||
5054 | return v; | ||||||||||||
5055 | v = isl_vec_cow(v); | ||||||||||||
5056 | if (!v) | ||||||||||||
5057 | return NULL((void*)0); | ||||||||||||
5058 | if (tightened
))) | ||||||||||||
5059 | *tightened = 1; | ||||||||||||
5060 | isl_int_fdiv_q(v->el[0], v->el[0], ctx->normalize_gcd)isl_sioimath_fdiv_q((v->el[0]), *(v->el[0]), *(ctx-> normalize_gcd)); | ||||||||||||
5061 | isl_seq_scale_down(v->el + 1, v->el + 1, ctx->normalize_gcd, | ||||||||||||
5062 | v->size - 1); | ||||||||||||
5063 | return v; | ||||||||||||
5064 | } | ||||||||||||
5065 | |||||||||||||
5066 | /* If "bmap" is an integer set that satisfies any equality involving | ||||||||||||
5067 | * more than 2 variables and/or has coefficients different from -1 and 1, | ||||||||||||
5068 | * then use variable compression to reduce the coefficients by removing | ||||||||||||
5069 | * any (hidden) common factor. | ||||||||||||
5070 | * In particular, apply the variable compression to each constraint, | ||||||||||||
5071 | * factor out any common factor in the non-constant coefficients and | ||||||||||||
5072 | * then apply the inverse of the compression. | ||||||||||||
5073 | * At the end, we mark the basic map as having reduced constants. | ||||||||||||
5074 | * If this flag is still set on the next invocation of this function, | ||||||||||||
5075 | * then we skip the computation. | ||||||||||||
5076 | * | ||||||||||||
5077 | * Removing a common factor may result in a tightening of some of | ||||||||||||
5078 | * the constraints. If this happens, then we may end up with two | ||||||||||||
5079 | * opposite inequalities that can be replaced by an equality. | ||||||||||||
5080 | * We therefore call isl_basic_map_detect_inequality_pairs, | ||||||||||||
5081 | * which checks for such pairs of inequalities as well as eliminate_divs_eq | ||||||||||||
5082 | * and isl_basic_map_gauss if such a pair was found. | ||||||||||||
5083 | * | ||||||||||||
5084 | * Note that this function may leave the result in an inconsistent state. | ||||||||||||
5085 | * In particular, the constraints may not be gaussed. | ||||||||||||
5086 | * Unfortunately, isl_map_coalesce actually depends on this inconsistent state | ||||||||||||
5087 | * for some of the test cases to pass successfully. | ||||||||||||
5088 | * Any potential modification of the representation is therefore only | ||||||||||||
5089 | * performed on a single copy of the basic map. | ||||||||||||
5090 | */ | ||||||||||||
5091 | __isl_give isl_basic_map *isl_basic_map_reduce_coefficients( | ||||||||||||
5092 | __isl_take isl_basic_map *bmap) | ||||||||||||
5093 | { | ||||||||||||
5094 | unsigned total; | ||||||||||||
5095 | isl_ctx *ctx; | ||||||||||||
5096 | isl_vec *v; | ||||||||||||
5097 | isl_mat *eq, *T, *T2; | ||||||||||||
5098 | int i; | ||||||||||||
5099 | int tightened; | ||||||||||||
5100 | |||||||||||||
5101 | if (!bmap) | ||||||||||||
| |||||||||||||
5102 | return NULL((void*)0); | ||||||||||||
5103 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS)(!!(((bmap)->flags) & ((1 << 8))))) | ||||||||||||
5104 | return bmap; | ||||||||||||
5105 | if (isl_basic_map_is_rational(bmap)) | ||||||||||||
5106 | return bmap; | ||||||||||||
5107 | if (bmap->n_eq == 0) | ||||||||||||
5108 | return bmap; | ||||||||||||
5109 | if (!has_multiple_var_equality(bmap)) | ||||||||||||
5110 | return bmap; | ||||||||||||
5111 | |||||||||||||
5112 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
5113 | ctx = isl_basic_map_get_ctx(bmap); | ||||||||||||
5114 | v = isl_vec_alloc(ctx, 1 + total); | ||||||||||||
5115 | if (!v) | ||||||||||||
5116 | return isl_basic_map_free(bmap); | ||||||||||||
5117 | |||||||||||||
5118 | eq = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total); | ||||||||||||
5119 | T = isl_mat_variable_compression(eq, &T2); | ||||||||||||
5120 | if (!T || !T2) | ||||||||||||
5121 | goto error; | ||||||||||||
5122 | if (T->n_col == 0) { | ||||||||||||
5123 | isl_mat_free(T); | ||||||||||||
5124 | isl_mat_free(T2); | ||||||||||||
5125 | isl_vec_free(v); | ||||||||||||
5126 | return isl_basic_map_set_to_empty(bmap); | ||||||||||||
5127 | } | ||||||||||||
5128 | |||||||||||||
5129 | bmap = isl_basic_map_cow(bmap); | ||||||||||||
5130 | if (!bmap) | ||||||||||||
5131 | goto error; | ||||||||||||
5132 | |||||||||||||
5133 | tightened = 0; | ||||||||||||
5134 | for (i = 0; i < bmap->n_ineq; ++i) { | ||||||||||||
5135 | isl_seq_cpy(v->el, bmap->ineq[i], 1 + total); | ||||||||||||
5136 | v = isl_vec_mat_product(v, isl_mat_copy(T)); | ||||||||||||
5137 | v = normalize_constraint(v, &tightened); | ||||||||||||
5138 | v = isl_vec_mat_product(v, isl_mat_copy(T2)); | ||||||||||||
5139 | if (!v) | ||||||||||||
5140 | goto error; | ||||||||||||
5141 | isl_seq_cpy(bmap->ineq[i], v->el, 1 + total); | ||||||||||||
5142 | } | ||||||||||||
5143 | |||||||||||||
5144 | isl_mat_free(T); | ||||||||||||
5145 | isl_mat_free(T2); | ||||||||||||
5146 | isl_vec_free(v); | ||||||||||||
5147 | |||||||||||||
5148 | ISL_F_SET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS)(((bmap)->flags) |= ((1 << 8))); | ||||||||||||
5149 | |||||||||||||
5150 | if (tightened
| ||||||||||||
5151 | int progress = 0; | ||||||||||||
5152 | |||||||||||||
5153 | bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress); | ||||||||||||
5154 | if (progress) { | ||||||||||||
5155 | bmap = eliminate_divs_eq(bmap, &progress); | ||||||||||||
5156 | bmap = isl_basic_map_gauss(bmap, NULL((void*)0)); | ||||||||||||
5157 | } | ||||||||||||
5158 | } | ||||||||||||
5159 | |||||||||||||
5160 | return bmap; | ||||||||||||
5161 | error: | ||||||||||||
5162 | isl_mat_free(T); | ||||||||||||
5163 | isl_mat_free(T2); | ||||||||||||
5164 | isl_vec_free(v); | ||||||||||||
5165 | return isl_basic_map_free(bmap); | ||||||||||||
5166 | } | ||||||||||||
5167 | |||||||||||||
5168 | /* Shift the integer division at position "div" of "bmap" | ||||||||||||
5169 | * by "shift" times the variable at position "pos". | ||||||||||||
5170 | * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0 | ||||||||||||
5171 | * corresponds to the constant term. | ||||||||||||
5172 | * | ||||||||||||
5173 | * That is, if the integer division has the form | ||||||||||||
5174 | * | ||||||||||||
5175 | * floor(f(x)/d) | ||||||||||||
5176 | * | ||||||||||||
5177 | * then replace it by | ||||||||||||
5178 | * | ||||||||||||
5179 | * floor((f(x) + shift * d * x_pos)/d) - shift * x_pos | ||||||||||||
5180 | */ | ||||||||||||
5181 | __isl_give isl_basic_map *isl_basic_map_shift_div( | ||||||||||||
5182 | __isl_take isl_basic_map *bmap, int div, int pos, isl_int shift) | ||||||||||||
5183 | { | ||||||||||||
5184 | int i; | ||||||||||||
5185 | unsigned total; | ||||||||||||
5186 | |||||||||||||
5187 | if (isl_int_is_zero(shift)(isl_sioimath_sgn(*(shift)) == 0)) | ||||||||||||
5188 | return bmap; | ||||||||||||
5189 | if (!bmap) | ||||||||||||
5190 | return NULL((void*)0); | ||||||||||||
5191 | |||||||||||||
5192 | total = isl_basic_map_dim(bmap, isl_dim_all); | ||||||||||||
5193 | total -= isl_basic_map_dim(bmap, isl_dim_div); | ||||||||||||
5194 | |||||||||||||
5195 | isl_int_addmul(bmap->div[div][1 + pos], shift, bmap->div[div][0])isl_sioimath_addmul((bmap->div[div][1 + pos]), *(shift), * (bmap->div[div][0])); | ||||||||||||
5196 | |||||||||||||
5197 | for (i = 0; i < bmap->n_eq; ++i) { | ||||||||||||
5198 | if (isl_int_is_zero(bmap->eq[i][1 + total + div])(isl_sioimath_sgn(*(bmap->eq[i][1 + total + div])) == 0)) | ||||||||||||
5199 | continue; | ||||||||||||
5200 | isl_int_submul(bmap->eq[i][pos],isl_sioimath_submul((bmap->eq[i][pos]), *(shift), *(bmap-> eq[i][1 + total + div])) | ||||||||||||
5201 | shift, bmap->eq[i][1 + total + div])isl_sioimath_submul((bmap->eq[i][pos]), *(shift), *(bmap-> eq[i][1 + total + div])); | ||||||||||||
5202 | } | ||||||||||||
5203 | for (i = 0; i < bmap->n_ineq; ++i) { | ||||||||||||
5204 | if (isl_int_is_zero(bmap->ineq[i][1 + total + div])(isl_sioimath_sgn(*(bmap->ineq[i][1 + total + div])) == 0)) | ||||||||||||
5205 | continue; | ||||||||||||
5206 | isl_int_submul(bmap->ineq[i][pos],isl_sioimath_submul((bmap->ineq[i][pos]), *(shift), *(bmap ->ineq[i][1 + total + div])) | ||||||||||||
5207 | shift, bmap->ineq[i][1 + total + div])isl_sioimath_submul((bmap->ineq[i][pos]), *(shift), *(bmap ->ineq[i][1 + total + div])); | ||||||||||||
5208 | } | ||||||||||||
5209 | for (i = 0; i < bmap->n_div; ++i) { | ||||||||||||
5210 | if (isl_int_is_zero(bmap->div[i][0])(isl_sioimath_sgn(*(bmap->div[i][0])) == 0)) | ||||||||||||
5211 | continue; | ||||||||||||
5212 | if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div])(isl_sioimath_sgn(*(bmap->div[i][1 + 1 + total + div])) == 0)) | ||||||||||||
5213 | continue; | ||||||||||||
5214 | isl_int_submul(bmap->div[i][1 + pos],isl_sioimath_submul((bmap->div[i][1 + pos]), *(shift), *(bmap ->div[i][1 + 1 + total + div])) | ||||||||||||
5215 | shift, bmap->div[i][1 + 1 + total + div])isl_sioimath_submul((bmap->div[i][1 + pos]), *(shift), *(bmap ->div[i][1 + 1 + total + div])); | ||||||||||||
5216 | } | ||||||||||||
5217 | |||||||||||||
5218 | return bmap; | ||||||||||||
5219 | } |
1 | /* |
2 | * Copyright 2015 INRIA Paris-Rocquencourt |
3 | * |
4 | * Use of this software is governed by the MIT license |
5 | * |
6 | * Written by Michael Kruse, INRIA Paris-Rocquencourt, |
7 | * Domaine de Voluceau, Rocquenqourt, B.P. 105, |
8 | * 78153 Le Chesnay Cedex France |
9 | */ |
10 | #ifndef ISL_INT_SIOIMATH_H |
11 | #define ISL_INT_SIOIMATH_H |
12 | |
13 | #include <inttypes.h> |
14 | #include <limits.h> |
15 | #include <stdint.h> |
16 | #include <stdlib.h> |
17 | |
18 | #include <isl_imath.h> |
19 | #include <isl/hash.h> |
20 | |
21 | #define ARRAY_SIZE(array)(sizeof(array)/sizeof(*array)) (sizeof(array)/sizeof(*array)) |
22 | |
23 | /* Visual Studio before VS2015 does not support the inline keyword when |
24 | * compiling in C mode because it was introduced in C99 which it does not |
25 | * officially support. Instead, it has a proprietary extension using __inline. |
26 | */ |
27 | #if defined(_MSC_VER) && (_MSC_VER < 1900) |
28 | #define inline __inline |
29 | #endif |
30 | |
31 | /* The type to represent integers optimized for small values. It is either a |
32 | * pointer to an mp_int ( = mpz_t*; big representation) or an int32_t (small |
33 | * represenation) with a discriminator at the least significant bit. In big |
34 | * representation it will be always zero because of heap alignment. It is set |
35 | * to 1 for small representation and use the 32 most significant bits for the |
36 | * int32_t. |
37 | * |
38 | * Structure on 64 bit machines, with 8-byte aligment (3 bits): |
39 | * |
40 | * Big representation: |
41 | * MSB LSB |
42 | * |------------------------------------------------------------000 |
43 | * | mpz_t* | |
44 | * | != NULL | |
45 | * |
46 | * Small representation: |
47 | * MSB 32 LSB |
48 | * |------------------------------|00000000000000000000000000000001 |
49 | * | int32_t | |
50 | * | 2147483647 ... -2147483647 | |
51 | * ^ |
52 | * | |
53 | * discriminator bit |
54 | * |
55 | * On 32 bit machines isl_sioimath type is blown up to 8 bytes, i.e. |
56 | * isl_sioimath is guaranteed to be at least 8 bytes. This is to ensure the |
57 | * int32_t can be hidden in that type without data loss. In the future we might |
58 | * optimize this to use 31 hidden bits in a 32 bit pointer. We may also use 63 |
59 | * bits on 64 bit machines, but this comes with the cost of additional overflow |
60 | * checks because there is no standardized 128 bit integer we could expand to. |
61 | * |
62 | * We use native integer types and avoid union structures to avoid assumptions |
63 | * on the machine's endianness. |
64 | * |
65 | * This implementation makes the following assumptions: |
66 | * - long can represent any int32_t |
67 | * - mp_small is signed long |
68 | * - mp_usmall is unsigned long |
69 | * - adresses returned by malloc are aligned to 2-byte boundaries (leastmost |
70 | * bit is zero) |
71 | */ |
72 | #if UINT64_MAX(18446744073709551615UL) > UINTPTR_MAX(18446744073709551615UL) |
73 | typedef uint64_t isl_sioimath; |
74 | #else |
75 | typedef uintptr_t isl_sioimath; |
76 | #endif |
77 | |
78 | /* The negation of the smallest possible number in int32_t, INT32_MIN |
79 | * (0x80000000u, -2147483648), cannot be represented in an int32_t, therefore |
80 | * every operation that may produce this value needs to special-case it. |
81 | * The operations are: |
82 | * abs(INT32_MIN) |
83 | * -INT32_MIN (negation) |
84 | * -1 * INT32_MIN (multiplication) |
85 | * INT32_MIN/-1 (any division: divexact, fdiv, cdiv, tdiv) |
86 | * To avoid checking these cases, we exclude INT32_MIN from small |
87 | * representation. |
88 | */ |
89 | #define ISL_SIOIMATH_SMALL_MIN(-(2147483647)) (-INT32_MAX(2147483647)) |
90 | |
91 | /* Largest possible number in small representation */ |
92 | #define ISL_SIOIMATH_SMALL_MAX(2147483647) INT32_MAX(2147483647) |
93 | |
94 | /* Used for function parameters the function modifies. */ |
95 | typedef isl_sioimath *isl_sioimath_ptr; |
96 | |
97 | /* Used for function parameters that are read-only. */ |
98 | typedef isl_sioimath isl_sioimath_src; |
99 | |
100 | /* Return whether the argument is stored in small representation. |
101 | */ |
102 | inline int isl_sioimath_is_small(isl_sioimath val) |
103 | { |
104 | return val & 0x00000001; |
105 | } |
106 | |
107 | /* Return whether the argument is stored in big representation. |
108 | */ |
109 | inline int isl_sioimath_is_big(isl_sioimath val) |
110 | { |
111 | return !isl_sioimath_is_small(val); |
112 | } |
113 | |
114 | /* Get the number of an isl_int in small representation. Result is undefined if |
115 | * val is not stored in that format. |
116 | */ |
117 | inline int32_t isl_sioimath_get_small(isl_sioimath val) |
118 | { |
119 | return val >> 32; |
120 | } |
121 | |
122 | /* Get the number of an in isl_int in big representation. Result is undefined if |
123 | * val is not stored in that format. |
124 | */ |
125 | inline mp_int isl_sioimath_get_big(isl_sioimath val) |
126 | { |
127 | return (mp_int)(uintptr_t) val; |
128 | } |
129 | |
130 | /* Return 1 if val is stored in small representation and store its value to |
131 | * small. We rely on the compiler to optimize the isl_sioimath_get_small such |
132 | * that the shift is moved into the branch that executes in case of small |
133 | * representation. If there is no such branch, then a single shift is still |
134 | * cheaper than introducing branching code. |
135 | */ |
136 | inline int isl_sioimath_decode_small(isl_sioimath val, int32_t *small) |
137 | { |
138 | *small = isl_sioimath_get_small(val); |
139 | return isl_sioimath_is_small(val); |
140 | } |
141 | |
142 | /* Return 1 if val is stored in big representation and store its value to big. |
143 | */ |
144 | inline int isl_sioimath_decode_big(isl_sioimath val, mp_int *big) |
145 | { |
146 | *big = isl_sioimath_get_big(val); |
147 | return isl_sioimath_is_big(val); |
148 | } |
149 | |
150 | /* Encode a small representation into an isl_int. |
151 | */ |
152 | inline isl_sioimath isl_sioimath_encode_small(int32_t val) |
153 | { |
154 | return ((isl_sioimath) val) << 32 | 0x00000001; |
155 | } |
156 | |
157 | /* Encode a big representation. |
158 | */ |
159 | inline isl_sioimath isl_sioimath_encode_big(mp_int val) |
160 | { |
161 | return (isl_sioimath)(uintptr_t) val; |
162 | } |
163 | |
164 | /* A common situation is to call an IMath function with at least one argument |
165 | * that is currently in small representation or an integer parameter, i.e. a big |
166 | * representation of the same number is required. Promoting the original |
167 | * argument comes with multiple problems, such as modifying a read-only |
168 | * argument, the responsibility of deallocation and the execution cost. Instead, |
169 | * we make a copy by 'faking' the IMath internal structure. |
170 | * |
171 | * We reserve the maximum number of required digits on the stack to avoid heap |
172 | * allocations. |
173 | * |
174 | * mp_digit can be uint32_t or uint16_t. This code must work for little and big |
175 | * endian digits. The structure for an uint64_t argument and 32-bit mp_digits is |
176 | * sketched below. |
177 | * |
178 | * |----------------------------| |
179 | * uint64_t |
180 | * |
181 | * |-------------||-------------| |
182 | * mp_digit mp_digit |
183 | * digits[1] digits[0] |
184 | * Most sig digit Least sig digit |
185 | */ |
186 | typedef struct { |
187 | mpz_t big; |
188 | mp_digit digits[(sizeof(uintmax_t) + sizeof(mp_digit) - 1) / |
189 | sizeof(mp_digit)]; |
190 | } isl_sioimath_scratchspace_t; |
191 | |
192 | /* Convert a native integer to IMath's digit representation. A native integer |
193 | * might be big- or little endian, but IMath always stores the least significant |
194 | * digit in the lowest array indices. memcpy therefore is not possible. |
195 | * |
196 | * We also have to consider that long and mp_digit can be of different sizes, |
197 | * depending on the compiler (LP64, LLP64) and IMath's USE_64BIT_WORDS. This |
198 | * macro should work for all of them. |
199 | * |
200 | * "used" is set to the number of written digits. It must be minimal (IMath |
201 | * checks zeroness using the used field), but always at least one. Also note |
202 | * that the result of num>>(sizeof(num)*CHAR_BIT) is undefined. |
203 | */ |
204 | #define ISL_SIOIMATH_TO_DIGITS(num, digits, used)do { int i = 0; do { (digits)[i] = ((num) >> (sizeof(mp_digit ) * 8 * i)); i += 1; if (i >= (sizeof(num) + sizeof(mp_digit ) - 1) / sizeof(mp_digit)) break; if (((num) >> (sizeof (mp_digit) * 8 * i)) == 0) break; } while (1); (used) = i; } while (0) \ |
205 | do { \ |
206 | int i = 0; \ |
207 | do { \ |
208 | (digits)[i] = \ |
209 | ((num) >> (sizeof(mp_digit) * CHAR_BIT8 * i)); \ |
210 | i += 1; \ |
211 | if (i >= (sizeof(num) + sizeof(mp_digit) - 1) / \ |
212 | sizeof(mp_digit)) \ |
213 | break; \ |
214 | if (((num) >> (sizeof(mp_digit) * CHAR_BIT8 * i)) == 0) \ |
215 | break; \ |
216 | } while (1); \ |
217 | (used) = i; \ |
218 | } while (0) |
219 | |
220 | inline void isl_siomath_uint32_to_digits(uint32_t num, mp_digit *digits, |
221 | mp_size *used) |
222 | { |
223 | ISL_SIOIMATH_TO_DIGITS(num, digits, *used)do { int i = 0; do { (digits)[i] = ((num) >> (sizeof(mp_digit ) * 8 * i)); i += 1; if (i >= (sizeof(num) + sizeof(mp_digit ) - 1) / sizeof(mp_digit)) break; if (((num) >> (sizeof (mp_digit) * 8 * i)) == 0) break; } while (1); (*used) = i; } while (0); |
224 | } |
225 | |
226 | inline void isl_siomath_ulong_to_digits(unsigned long num, mp_digit *digits, |
227 | mp_size *used) |
228 | { |
229 | ISL_SIOIMATH_TO_DIGITS(num, digits, *used)do { int i = 0; do { (digits)[i] = ((num) >> (sizeof(mp_digit ) * 8 * i)); i += 1; if (i >= (sizeof(num) + sizeof(mp_digit ) - 1) / sizeof(mp_digit)) break; if (((num) >> (sizeof (mp_digit) * 8 * i)) == 0) break; } while (1); (*used) = i; } while (0); |
230 | } |
231 | |
232 | inline void isl_siomath_uint64_to_digits(uint64_t num, mp_digit *digits, |
233 | mp_size *used) |
234 | { |
235 | ISL_SIOIMATH_TO_DIGITS(num, digits, *used)do { int i = 0; do { (digits)[i] = ((num) >> (sizeof(mp_digit ) * 8 * i)); i += 1; if (i >= (sizeof(num) + sizeof(mp_digit ) - 1) / sizeof(mp_digit)) break; if (((num) >> (sizeof (mp_digit) * 8 * i)) == 0) break; } while (1); (*used) = i; } while (0); |
236 | } |
237 | |
238 | /* Get the IMath representation of an isl_int without modifying it. |
239 | * For the case it is not in big representation yet, pass some scratch space we |
240 | * can use to store the big representation in. |
241 | * In order to avoid requiring init and free on the scratch space, we directly |
242 | * modify the internal representation. |
243 | * |
244 | * The name derives from its indented use: getting the big representation of an |
245 | * input (src) argument. |
246 | */ |
247 | inline mp_int isl_sioimath_bigarg_src(isl_sioimath arg, |
248 | isl_sioimath_scratchspace_t *scratch) |
249 | { |
250 | mp_int big; |
251 | int32_t small; |
252 | uint32_t num; |
253 | |
254 | if (isl_sioimath_decode_big(arg, &big)) |
255 | return big; |
256 | |
257 | small = isl_sioimath_get_small(arg); |
258 | scratch->big.digits = scratch->digits; |
259 | scratch->big.alloc = ARRAY_SIZE(scratch->digits)(sizeof(scratch->digits)/sizeof(*scratch->digits)); |
260 | if (small >= 0) { |
261 | scratch->big.sign = MP_ZPOS; |
262 | num = small; |
263 | } else { |
264 | scratch->big.sign = MP_NEG; |
265 | num = -small; |
266 | } |
267 | |
268 | isl_siomath_uint32_to_digits(num, scratch->digits, &scratch->big.used); |
269 | return &scratch->big; |
270 | } |
271 | |
272 | /* Create a temporary IMath mp_int for a signed long. |
273 | */ |
274 | inline mp_int isl_sioimath_siarg_src(signed long arg, |
275 | isl_sioimath_scratchspace_t *scratch) |
276 | { |
277 | unsigned long num; |
278 | |
279 | scratch->big.digits = scratch->digits; |
280 | scratch->big.alloc = ARRAY_SIZE(scratch->digits)(sizeof(scratch->digits)/sizeof(*scratch->digits)); |
281 | if (arg >= 0) { |
282 | scratch->big.sign = MP_ZPOS; |
283 | num = arg; |
284 | } else { |
285 | scratch->big.sign = MP_NEG; |
286 | num = (arg == LONG_MIN(-9223372036854775807L -1L)) ? ((unsigned long) LONG_MAX9223372036854775807L) + 1 : -arg; |
287 | } |
288 | |
289 | isl_siomath_ulong_to_digits(num, scratch->digits, &scratch->big.used); |
290 | return &scratch->big; |
291 | } |
292 | |
293 | /* Create a temporary IMath mp_int for an int64_t. |
294 | */ |
295 | inline mp_int isl_sioimath_si64arg_src(int64_t arg, |
296 | isl_sioimath_scratchspace_t *scratch) |
297 | { |
298 | uint64_t num; |
299 | |
300 | scratch->big.digits = scratch->digits; |
301 | scratch->big.alloc = ARRAY_SIZE(scratch->digits)(sizeof(scratch->digits)/sizeof(*scratch->digits)); |
302 | if (arg >= 0) { |
303 | scratch->big.sign = MP_ZPOS; |
304 | num = arg; |
305 | } else { |
306 | scratch->big.sign = MP_NEG; |
307 | num = (arg == INT64_MIN(-9223372036854775807L -1)) ? ((uint64_t) INT64_MAX(9223372036854775807L)) + 1 : -arg; |
308 | } |
309 | |
310 | isl_siomath_uint64_to_digits(num, scratch->digits, &scratch->big.used); |
311 | return &scratch->big; |
312 | } |
313 | |
314 | /* Create a temporary IMath mp_int for an unsigned long. |
315 | */ |
316 | inline mp_int isl_sioimath_uiarg_src(unsigned long arg, |
317 | isl_sioimath_scratchspace_t *scratch) |
318 | { |
319 | scratch->big.digits = scratch->digits; |
320 | scratch->big.alloc = ARRAY_SIZE(scratch->digits)(sizeof(scratch->digits)/sizeof(*scratch->digits)); |
321 | scratch->big.sign = MP_ZPOS; |
322 | |
323 | isl_siomath_ulong_to_digits(arg, scratch->digits, &scratch->big.used); |
324 | return &scratch->big; |
325 | } |
326 | |
327 | /* Ensure big representation. Does not preserve the current number. |
328 | * Callers may use the fact that the value _is_ preserved if the presentation |
329 | * was big before. |
330 | */ |
331 | inline mp_int isl_sioimath_reinit_big(isl_sioimath_ptr ptr) |
332 | { |
333 | if (isl_sioimath_is_small(*ptr)) |
334 | *ptr = isl_sioimath_encode_big(mp_int_alloc()); |
335 | return isl_sioimath_get_big(*ptr); |
336 | } |
337 | |
338 | /* Set ptr to a number in small representation. |
339 | */ |
340 | inline void isl_sioimath_set_small(isl_sioimath_ptr ptr, int32_t val) |
341 | { |
342 | if (isl_sioimath_is_big(*ptr)) |
343 | mp_int_free(isl_sioimath_get_big(*ptr)); |
344 | *ptr = isl_sioimath_encode_small(val); |
345 | } |
346 | |
347 | /* Set ptr to val, choosing small representation if possible. |
348 | */ |
349 | inline void isl_sioimath_set_int32(isl_sioimath_ptr ptr, int32_t val) |
350 | { |
351 | if (ISL_SIOIMATH_SMALL_MIN(-(2147483647)) <= val && val <= ISL_SIOIMATH_SMALL_MAX(2147483647)) { |
352 | isl_sioimath_set_small(ptr, val); |
353 | return; |
354 | } |
355 | |
356 | mp_int_init_value(isl_sioimath_reinit_big(ptr), val); |
357 | } |
358 | |
359 | /* Assign an int64_t number using small representation if possible. |
360 | */ |
361 | inline void isl_sioimath_set_int64(isl_sioimath_ptr ptr, int64_t val) |
362 | { |
363 | if (ISL_SIOIMATH_SMALL_MIN(-(2147483647)) <= val && val <= ISL_SIOIMATH_SMALL_MAX(2147483647)) { |
364 | isl_sioimath_set_small(ptr, val); |
365 | return; |
366 | } |
367 | |
368 | isl_sioimath_scratchspace_t scratch; |
369 | mp_int_copy(isl_sioimath_si64arg_src(val, &scratch), |
370 | isl_sioimath_reinit_big(ptr)); |
371 | } |
372 | |
373 | /* Convert to big representation while preserving the current number. |
374 | */ |
375 | inline void isl_sioimath_promote(isl_sioimath_ptr dst) |
376 | { |
377 | int32_t small; |
378 | |
379 | if (isl_sioimath_is_big(*dst)) |
380 | return; |
381 | |
382 | small = isl_sioimath_get_small(*dst); |
383 | mp_int_set_value(isl_sioimath_reinit_big(dst), small); |
384 | } |
385 | |
386 | /* Convert to small representation while preserving the current number. Does |
387 | * nothing if dst doesn't fit small representation. |
388 | */ |
389 | inline void isl_sioimath_try_demote(isl_sioimath_ptr dst) |
390 | { |
391 | mp_small small; |
392 | |
393 | if (isl_sioimath_is_small(*dst)) |
394 | return; |
395 | |
396 | if (mp_int_to_int(isl_sioimath_get_big(*dst), &small) != MP_OK) |
397 | return; |
398 | |
399 | if (ISL_SIOIMATH_SMALL_MIN(-(2147483647)) <= small && small <= ISL_SIOIMATH_SMALL_MAX(2147483647)) |
400 | isl_sioimath_set_small(dst, small); |
401 | } |
402 | |
403 | /* Initialize an isl_int. The implicit value is 0 in small representation. |
404 | */ |
405 | inline void isl_sioimath_init(isl_sioimath_ptr dst) |
406 | { |
407 | *dst = isl_sioimath_encode_small(0); |
408 | } |
409 | |
410 | /* Free the resources taken by an isl_int. |
411 | */ |
412 | inline void isl_sioimath_clear(isl_sioimath_ptr dst) |
413 | { |
414 | if (isl_sioimath_is_small(*dst)) |
415 | return; |
416 | |
417 | mp_int_free(isl_sioimath_get_big(*dst)); |
418 | } |
419 | |
420 | /* Copy the value of one isl_int to another. |
421 | */ |
422 | inline void isl_sioimath_set(isl_sioimath_ptr dst, isl_sioimath_src val) |
423 | { |
424 | if (isl_sioimath_is_small(val)) { |
425 | isl_sioimath_set_small(dst, isl_sioimath_get_small(val)); |
426 | return; |
427 | } |
428 | |
429 | mp_int_copy(isl_sioimath_get_big(val), isl_sioimath_reinit_big(dst)); |
430 | } |
431 | |
432 | /* Store a signed long into an isl_int. |
433 | */ |
434 | inline void isl_sioimath_set_si(isl_sioimath_ptr dst, long val) |
435 | { |
436 | if (ISL_SIOIMATH_SMALL_MIN(-(2147483647)) <= val && val <= ISL_SIOIMATH_SMALL_MAX(2147483647)) { |
437 | isl_sioimath_set_small(dst, val); |
438 | return; |
439 | } |
440 | |
441 | mp_int_set_value(isl_sioimath_reinit_big(dst), val); |
442 | } |
443 | |
444 | /* Store an unsigned long into an isl_int. |
445 | */ |
446 | inline void isl_sioimath_set_ui(isl_sioimath_ptr dst, unsigned long val) |
447 | { |
448 | if (val <= ISL_SIOIMATH_SMALL_MAX(2147483647)) { |
449 | isl_sioimath_set_small(dst, val); |
450 | return; |
451 | } |
452 | |
453 | mp_int_set_uvalue(isl_sioimath_reinit_big(dst), val); |
454 | } |
455 | |
456 | /* Return whether a number can be represented by a signed long. |
457 | */ |
458 | inline int isl_sioimath_fits_slong(isl_sioimath_src val) |
459 | { |
460 | mp_small dummy; |
461 | |
462 | if (isl_sioimath_is_small(val)) |
463 | return 1; |
464 | |
465 | return mp_int_to_int(isl_sioimath_get_big(val), &dummy) == MP_OK; |
466 | } |
467 | |
468 | /* Return a number as signed long. Result is undefined if the number cannot be |
469 | * represented as long. |
470 | */ |
471 | inline long isl_sioimath_get_si(isl_sioimath_src val) |
472 | { |
473 | mp_small result; |
474 | |
475 | if (isl_sioimath_is_small(val)) |
476 | return isl_sioimath_get_small(val); |
477 | |
478 | mp_int_to_int(isl_sioimath_get_big(val), &result); |
479 | return result; |
480 | } |
481 | |
482 | /* Return whether a number can be represented as unsigned long. |
483 | */ |
484 | inline int isl_sioimath_fits_ulong(isl_sioimath_src val) |
485 | { |
486 | mp_usmall dummy; |
487 | |
488 | if (isl_sioimath_is_small(val)) |
489 | return isl_sioimath_get_small(val) >= 0; |
490 | |
491 | return mp_int_to_uint(isl_sioimath_get_big(val), &dummy) == MP_OK; |
492 | } |
493 | |
494 | /* Return a number as unsigned long. Result is undefined if the number cannot be |
495 | * represented as unsigned long. |
496 | */ |
497 | inline unsigned long isl_sioimath_get_ui(isl_sioimath_src val) |
498 | { |
499 | mp_usmall result; |
500 | |
501 | if (isl_sioimath_is_small(val)) |
502 | return isl_sioimath_get_small(val); |
503 | |
504 | mp_int_to_uint(isl_sioimath_get_big(val), &result); |
505 | return result; |
506 | } |
507 | |
508 | /* Return a number as floating point value. |
509 | */ |
510 | inline double isl_sioimath_get_d(isl_sioimath_src val) |
511 | { |
512 | mp_int big; |
513 | double result = 0; |
514 | int i; |
515 | |
516 | if (isl_sioimath_is_small(val)) |
517 | return isl_sioimath_get_small(val); |
518 | |
519 | big = isl_sioimath_get_big(val); |
520 | for (i = 0; i < big->used; ++i) |
521 | result = result * (double) ((uintmax_t) MP_DIGIT_MAX((4294967295U) * 1UL) + 1) + |
522 | (double) big->digits[i]; |
523 | |
524 | if (big->sign == MP_NEG) |
525 | result = -result; |
526 | |
527 | return result; |
528 | } |
529 | |
530 | /* Format a number as decimal string. |
531 | * |
532 | * The largest possible string from small representation is 12 characters |
533 | * ("-2147483647"). |
534 | */ |
535 | inline char *isl_sioimath_get_str(isl_sioimath_src val) |
536 | { |
537 | char *result; |
538 | |
539 | if (isl_sioimath_is_small(val)) { |
540 | result = malloc(12); |
541 | snprintf(result, 12, "%" PRIi32"i", isl_sioimath_get_small(val)); |
542 | return result; |
543 | } |
544 | |
545 | return impz_get_str(NULL((void*)0), 10, isl_sioimath_get_big(val)); |
546 | } |
547 | |
548 | /* Return the absolute value. |
549 | */ |
550 | inline void isl_sioimath_abs(isl_sioimath_ptr dst, isl_sioimath_src arg) |
551 | { |
552 | if (isl_sioimath_is_small(arg)) { |
553 | isl_sioimath_set_small(dst, labs(isl_sioimath_get_small(arg))); |
554 | return; |
555 | } |
556 | |
557 | mp_int_abs(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst)); |
558 | } |
559 | |
560 | /* Return the negation of a number. |
561 | */ |
562 | inline void isl_sioimath_neg(isl_sioimath_ptr dst, isl_sioimath_src arg) |
563 | { |
564 | if (isl_sioimath_is_small(arg)) { |
565 | isl_sioimath_set_small(dst, -isl_sioimath_get_small(arg)); |
566 | return; |
567 | } |
568 | |
569 | mp_int_neg(isl_sioimath_get_big(arg), isl_sioimath_reinit_big(dst)); |
570 | } |
571 | |
572 | /* Swap two isl_ints. |
573 | * |
574 | * isl_sioimath can be copied bytewise; nothing depends on its address. It can |
575 | * also be stored in a CPU register. |
576 | */ |
577 | inline void isl_sioimath_swap(isl_sioimath_ptr lhs, isl_sioimath_ptr rhs) |
578 | { |
579 | isl_sioimath tmp = *lhs; |
580 | *lhs = *rhs; |
581 | *rhs = tmp; |
582 | } |
583 | |
584 | /* Add an unsigned long to the number. |
585 | * |
586 | * On LP64 unsigned long exceeds the range of an int64_t, therefore we check in |
587 | * advance whether small representation possibly overflows. |
588 | */ |
589 | inline void isl_sioimath_add_ui(isl_sioimath_ptr dst, isl_sioimath lhs, |
590 | unsigned long rhs) |
591 | { |
592 | int32_t smalllhs; |
593 | isl_sioimath_scratchspace_t lhsscratch; |
594 | |
595 | if (isl_sioimath_decode_small(lhs, &smalllhs) && |
596 | (rhs <= (uint64_t) INT64_MAX(9223372036854775807L) - (uint64_t) ISL_SIOIMATH_SMALL_MAX(2147483647))) { |
597 | isl_sioimath_set_int64(dst, (int64_t) smalllhs + rhs); |
598 | return; |
599 | } |
600 | |
601 | impz_add_ui(isl_sioimath_reinit_big(dst), |
602 | isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs); |
603 | isl_sioimath_try_demote(dst); |
604 | } |
605 | |
606 | /* Subtract an unsigned long. |
607 | * |
608 | * On LP64 unsigned long exceeds the range of an int64_t. If |
609 | * ISL_SIOIMATH_SMALL_MIN-rhs>=INT64_MIN we can do the calculation using int64_t |
610 | * without risking an overflow. |
611 | */ |
612 | inline void isl_sioimath_sub_ui(isl_sioimath_ptr dst, isl_sioimath lhs, |
613 | unsigned long rhs) |
614 | { |
615 | int32_t smalllhs; |
616 | isl_sioimath_scratchspace_t lhsscratch; |
617 | |
618 | if (isl_sioimath_decode_small(lhs, &smalllhs) && |
619 | (rhs < (uint64_t) INT64_MIN(-9223372036854775807L -1) - (uint64_t) ISL_SIOIMATH_SMALL_MIN(-(2147483647)))) { |
620 | isl_sioimath_set_int64(dst, (int64_t) smalllhs - rhs); |
621 | return; |
622 | } |
623 | |
624 | impz_sub_ui(isl_sioimath_reinit_big(dst), |
625 | isl_sioimath_bigarg_src(lhs, &lhsscratch), rhs); |
626 | isl_sioimath_try_demote(dst); |
627 | } |
628 | |
629 | /* Sum of two isl_ints. |
630 | */ |
631 | inline void isl_sioimath_add(isl_sioimath_ptr dst, isl_sioimath_src lhs, |
632 | isl_sioimath_src rhs) |
633 | { |
634 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
635 | int32_t smalllhs, smallrhs; |
636 | |
637 | if (isl_sioimath_decode_small(lhs, &smalllhs) && |
638 | isl_sioimath_decode_small(rhs, &smallrhs)) { |
639 | isl_sioimath_set_int64( |
640 | dst, (int64_t) smalllhs + (int64_t) smallrhs); |
641 | return; |
642 | } |
643 | |
644 | mp_int_add(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
645 | isl_sioimath_bigarg_src(rhs, &scratchrhs), |
646 | isl_sioimath_reinit_big(dst)); |
647 | isl_sioimath_try_demote(dst); |
648 | } |
649 | |
650 | /* Subtract two isl_ints. |
651 | */ |
652 | inline void isl_sioimath_sub(isl_sioimath_ptr dst, isl_sioimath_src lhs, |
653 | isl_sioimath_src rhs) |
654 | { |
655 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
656 | int32_t smalllhs, smallrhs; |
657 | |
658 | if (isl_sioimath_decode_small(lhs, &smalllhs) && |
659 | isl_sioimath_decode_small(rhs, &smallrhs)) { |
660 | isl_sioimath_set_int64( |
661 | dst, (int64_t) smalllhs - (int64_t) smallrhs); |
662 | return; |
663 | } |
664 | |
665 | mp_int_sub(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
666 | isl_sioimath_bigarg_src(rhs, &scratchrhs), |
667 | isl_sioimath_reinit_big(dst)); |
668 | isl_sioimath_try_demote(dst); |
669 | } |
670 | |
671 | /* Multiply two isl_ints. |
672 | */ |
673 | inline void isl_sioimath_mul(isl_sioimath_ptr dst, isl_sioimath_src lhs, |
674 | isl_sioimath_src rhs) |
675 | { |
676 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
677 | int32_t smalllhs, smallrhs; |
678 | |
679 | if (isl_sioimath_decode_small(lhs, &smalllhs) && |
680 | isl_sioimath_decode_small(rhs, &smallrhs)) { |
681 | isl_sioimath_set_int64( |
682 | dst, (int64_t) smalllhs * (int64_t) smallrhs); |
683 | return; |
684 | } |
685 | |
686 | mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
687 | isl_sioimath_bigarg_src(rhs, &scratchrhs), |
688 | isl_sioimath_reinit_big(dst)); |
689 | isl_sioimath_try_demote(dst); |
690 | } |
691 | |
692 | /* Shift lhs by rhs bits to the left and store the result in dst. Effectively, |
693 | * this operation computes 'lhs * 2^rhs'. |
694 | */ |
695 | inline void isl_sioimath_mul_2exp(isl_sioimath_ptr dst, isl_sioimath lhs, |
696 | unsigned long rhs) |
697 | { |
698 | isl_sioimath_scratchspace_t scratchlhs; |
699 | int32_t smalllhs; |
700 | |
701 | if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= 32ul)) { |
702 | isl_sioimath_set_int64(dst, ((int64_t) smalllhs) << rhs); |
703 | return; |
704 | } |
705 | |
706 | mp_int_mul_pow2(isl_sioimath_bigarg_src(lhs, &scratchlhs), rhs, |
707 | isl_sioimath_reinit_big(dst)); |
708 | } |
709 | |
710 | /* Multiply an isl_int and a signed long. |
711 | */ |
712 | inline void isl_sioimath_mul_si(isl_sioimath_ptr dst, isl_sioimath lhs, |
713 | signed long rhs) |
714 | { |
715 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
716 | int32_t smalllhs; |
717 | |
718 | if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs > LONG_MIN(-9223372036854775807L -1L)) && |
719 | (labs(rhs) <= UINT32_MAX(4294967295U))) { |
720 | isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs); |
721 | return; |
722 | } |
723 | |
724 | mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
725 | isl_sioimath_siarg_src(rhs, &scratchrhs), |
726 | isl_sioimath_reinit_big(dst)); |
727 | isl_sioimath_try_demote(dst); |
728 | } |
729 | |
730 | /* Multiply an isl_int and an unsigned long. |
731 | */ |
732 | inline void isl_sioimath_mul_ui(isl_sioimath_ptr dst, isl_sioimath lhs, |
733 | unsigned long rhs) |
734 | { |
735 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
736 | int32_t smalllhs; |
737 | |
738 | if (isl_sioimath_decode_small(lhs, &smalllhs) && (rhs <= UINT32_MAX(4294967295U))) { |
739 | isl_sioimath_set_int64(dst, (int64_t) smalllhs * (int64_t) rhs); |
740 | return; |
741 | } |
742 | |
743 | mp_int_mul(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
744 | isl_sioimath_uiarg_src(rhs, &scratchrhs), |
745 | isl_sioimath_reinit_big(dst)); |
746 | isl_sioimath_try_demote(dst); |
747 | } |
748 | |
749 | /* Compute the power of an isl_int to an unsigned long. |
750 | * Always let IMath do it; the result is unlikely to be small except in some |
751 | * special cases. |
752 | * Note: 0^0 == 1 |
753 | */ |
754 | inline void isl_sioimath_pow_ui(isl_sioimath_ptr dst, isl_sioimath_src lhs, |
755 | unsigned long rhs) |
756 | { |
757 | isl_sioimath_scratchspace_t scratchlhs, scratchrhs; |
758 | int32_t smalllhs; |
759 | |
760 | switch (rhs) { |
761 | case 0: |
762 | isl_sioimath_set_small(dst, 1); |
763 | return; |
764 | case 1: |
765 | isl_sioimath_set(dst, lhs); |
766 | return; |
767 | case 2: |
768 | isl_sioimath_mul(dst, lhs, lhs); |
769 | return; |
770 | } |
771 | |
772 | if (isl_sioimath_decode_small(lhs, &smalllhs)) { |
773 | switch (smalllhs) { |
774 | case 0: |
775 | isl_sioimath_set_small(dst, 0); |
776 | return; |
777 | case 1: |
778 | isl_sioimath_set_small(dst, 1); |
779 | return; |
780 | case 2: |
781 | isl_sioimath_set_small(dst, 1); |
782 | isl_sioimath_mul_2exp(dst, *dst, rhs); |
783 | return; |
784 | default: |
785 | if ((MP_SMALL_MIN(-9223372036854775807L -1L) <= rhs) && (rhs <= MP_SMALL_MAX9223372036854775807L)) { |
786 | mp_int_expt_value(smalllhs, rhs, |
787 | isl_sioimath_reinit_big(dst)); |
788 | isl_sioimath_try_demote(dst); |
789 | return; |
790 | } |
791 | } |
792 | } |
793 | |
794 | mp_int_expt_full(isl_sioimath_bigarg_src(lhs, &scratchlhs), |
795 | isl_sioimath_uiarg_src(rhs, &scratchrhs), |
796 | isl_sioimath_reinit_big(dst)); |
797 | isl_sioimath_try_demote(dst); |
798 | } |
799 | |
800 | /* Fused multiply-add. |
801 | */ |