File: | build/source/polly/lib/External/isl/isl_aff.c |
Warning: | line 2606, column 2 Value stored to 'ctx' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright 2011 INRIA Saclay |
3 | * Copyright 2011 Sven Verdoolaege |
4 | * Copyright 2012-2014 Ecole Normale Superieure |
5 | * Copyright 2014 INRIA Rocquencourt |
6 | * Copyright 2016 Sven Verdoolaege |
7 | * Copyright 2018,2020 Cerebras Systems |
8 | * Copyright 2021 Sven Verdoolaege |
9 | * |
10 | * Use of this software is governed by the MIT license |
11 | * |
12 | * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, |
13 | * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, |
14 | * 91893 Orsay, France |
15 | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France |
16 | * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, |
17 | * B.P. 105 - 78153 Le Chesnay, France |
18 | * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA |
19 | */ |
20 | |
21 | #include <isl_ctx_private.h> |
22 | #include <isl_map_private.h> |
23 | #include <isl_union_map_private.h> |
24 | #include <isl_aff_private.h> |
25 | #include <isl_space_private.h> |
26 | #include <isl_local_space_private.h> |
27 | #include <isl_vec_private.h> |
28 | #include <isl_mat_private.h> |
29 | #include <isl_id_private.h> |
30 | #include <isl/constraint.h> |
31 | #include <isl_seq.h> |
32 | #include <isl/set.h> |
33 | #include <isl_val_private.h> |
34 | #include <isl_point_private.h> |
35 | #include <isl_config.h> |
36 | |
37 | #undef EL_BASEunion_pw_aff |
38 | #define EL_BASEunion_pw_aff aff |
39 | |
40 | #include <isl_list_templ.c> |
41 | #include <isl_list_read_templ.c> |
42 | |
43 | #undef EL_BASEunion_pw_aff |
44 | #define EL_BASEunion_pw_aff pw_aff |
45 | |
46 | #include <isl_list_templ.c> |
47 | #include <isl_list_read_templ.c> |
48 | |
49 | #undef EL_BASEunion_pw_aff |
50 | #define EL_BASEunion_pw_aff pw_multi_aff |
51 | |
52 | #include <isl_list_templ.c> |
53 | #include <isl_list_read_templ.c> |
54 | |
55 | #undef EL_BASEunion_pw_aff |
56 | #define EL_BASEunion_pw_aff union_pw_aff |
57 | |
58 | #include <isl_list_templ.c> |
59 | #include <isl_list_read_templ.c> |
60 | |
61 | #undef EL_BASEunion_pw_aff |
62 | #define EL_BASEunion_pw_aff union_pw_multi_aff |
63 | |
64 | #include <isl_list_templ.c> |
65 | |
66 | __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls, |
67 | __isl_take isl_vec *v) |
68 | { |
69 | isl_aff *aff; |
70 | |
71 | if (!ls || !v) |
72 | goto error; |
73 | |
74 | aff = isl_calloc_type(v->ctx, struct isl_aff)((struct isl_aff *)isl_calloc_or_die(v->ctx, 1, sizeof(struct isl_aff))); |
75 | if (!aff) |
76 | goto error; |
77 | |
78 | aff->ref = 1; |
79 | aff->ls = ls; |
80 | aff->v = v; |
81 | |
82 | return aff; |
83 | error: |
84 | isl_local_space_free(ls); |
85 | isl_vec_free(v); |
86 | return NULL((void*)0); |
87 | } |
88 | |
89 | __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls) |
90 | { |
91 | isl_ctx *ctx; |
92 | isl_vec *v; |
93 | isl_size total; |
94 | |
95 | if (!ls) |
96 | return NULL((void*)0); |
97 | |
98 | ctx = isl_local_space_get_ctx(ls); |
99 | if (!isl_local_space_divs_known(ls)) |
100 | isl_die(ctx, isl_error_invalid, "local space has unknown divs",do { isl_handle_error(ctx, isl_error_invalid, "local space has unknown divs" , "polly/lib/External/isl/isl_aff.c", 101); goto error; } while (0) |
101 | goto error)do { isl_handle_error(ctx, isl_error_invalid, "local space has unknown divs" , "polly/lib/External/isl/isl_aff.c", 101); goto error; } while (0); |
102 | if (!isl_local_space_is_set(ls)) |
103 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "domain of affine expression should be a set" , "polly/lib/External/isl/isl_aff.c", 105); goto error; } while (0) |
104 | "domain of affine expression should be a set",do { isl_handle_error(ctx, isl_error_invalid, "domain of affine expression should be a set" , "polly/lib/External/isl/isl_aff.c", 105); goto error; } while (0) |
105 | goto error)do { isl_handle_error(ctx, isl_error_invalid, "domain of affine expression should be a set" , "polly/lib/External/isl/isl_aff.c", 105); goto error; } while (0); |
106 | |
107 | total = isl_local_space_dim(ls, isl_dim_all); |
108 | if (total < 0) |
109 | goto error; |
110 | v = isl_vec_alloc(ctx, 1 + 1 + total); |
111 | return isl_aff_alloc_vec(ls, v); |
112 | error: |
113 | isl_local_space_free(ls); |
114 | return NULL((void*)0); |
115 | } |
116 | |
117 | __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff) |
118 | { |
119 | if (!aff) |
120 | return NULL((void*)0); |
121 | |
122 | aff->ref++; |
123 | return aff; |
124 | } |
125 | |
126 | __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff) |
127 | { |
128 | if (!aff) |
129 | return NULL((void*)0); |
130 | |
131 | return isl_aff_alloc_vec(isl_local_space_copy(aff->ls), |
132 | isl_vec_copy(aff->v)); |
133 | } |
134 | |
135 | __isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff) |
136 | { |
137 | if (!aff) |
138 | return NULL((void*)0); |
139 | |
140 | if (aff->ref == 1) |
141 | return aff; |
142 | aff->ref--; |
143 | return isl_aff_dup(aff); |
144 | } |
145 | |
146 | __isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls) |
147 | { |
148 | isl_aff *aff; |
149 | |
150 | aff = isl_aff_alloc(ls); |
151 | if (!aff) |
152 | return NULL((void*)0); |
153 | |
154 | isl_int_set_si(aff->v->el[0], 1)isl_sioimath_set_si((aff->v->el[0]), 1); |
155 | isl_seq_clr(aff->v->el + 1, aff->v->size - 1); |
156 | |
157 | return aff; |
158 | } |
159 | |
160 | /* Return an affine expression that is equal to zero on domain space "space". |
161 | */ |
162 | __isl_give isl_aff *isl_aff_zero_on_domain_space(__isl_take isl_space *space) |
163 | { |
164 | return isl_aff_zero_on_domain(isl_local_space_from_space(space)); |
165 | } |
166 | |
167 | /* This function performs the same operation as isl_aff_zero_on_domain_space, |
168 | * but is considered as a function on an isl_space when exported. |
169 | */ |
170 | __isl_give isl_aff *isl_space_zero_aff_on_domain(__isl_take isl_space *space) |
171 | { |
172 | return isl_aff_zero_on_domain_space(space); |
173 | } |
174 | |
175 | /* Return a piecewise affine expression defined on the specified domain |
176 | * that is equal to zero. |
177 | */ |
178 | __isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls) |
179 | { |
180 | return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls)); |
181 | } |
182 | |
183 | /* Change "aff" into a NaN. |
184 | * |
185 | * Note that this function gets called from isl_aff_nan_on_domain, |
186 | * so "aff" may not have been initialized yet. |
187 | */ |
188 | static __isl_give isl_aff *isl_aff_set_nan(__isl_take isl_aff *aff) |
189 | { |
190 | aff = isl_aff_cow(aff); |
191 | if (!aff) |
192 | return NULL((void*)0); |
193 | |
194 | aff->v = isl_vec_clr(aff->v); |
195 | if (!aff->v) |
196 | return isl_aff_free(aff); |
197 | |
198 | return aff; |
199 | } |
200 | |
201 | /* Return an affine expression defined on the specified domain |
202 | * that represents NaN. |
203 | */ |
204 | __isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls) |
205 | { |
206 | isl_aff *aff; |
207 | |
208 | aff = isl_aff_alloc(ls); |
209 | return isl_aff_set_nan(aff); |
210 | } |
211 | |
212 | /* Return an affine expression defined on the specified domain space |
213 | * that represents NaN. |
214 | */ |
215 | __isl_give isl_aff *isl_aff_nan_on_domain_space(__isl_take isl_space *space) |
216 | { |
217 | return isl_aff_nan_on_domain(isl_local_space_from_space(space)); |
218 | } |
219 | |
220 | /* Return a piecewise affine expression defined on the specified domain space |
221 | * that represents NaN. |
222 | */ |
223 | __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain_space( |
224 | __isl_take isl_space *space) |
225 | { |
226 | return isl_pw_aff_from_aff(isl_aff_nan_on_domain_space(space)); |
227 | } |
228 | |
229 | /* Return a piecewise affine expression defined on the specified domain |
230 | * that represents NaN. |
231 | */ |
232 | __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls) |
233 | { |
234 | return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls)); |
235 | } |
236 | |
237 | /* Return an affine expression that is equal to "val" on |
238 | * domain local space "ls". |
239 | */ |
240 | __isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls, |
241 | __isl_take isl_val *val) |
242 | { |
243 | isl_aff *aff; |
244 | |
245 | if (!ls || !val) |
246 | goto error; |
247 | if (!isl_val_is_rat(val)) |
248 | isl_die(isl_val_get_ctx(val), isl_error_invalid,do { isl_handle_error(isl_val_get_ctx(val), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 249); goto error; } while (0) |
249 | "expecting rational value", goto error)do { isl_handle_error(isl_val_get_ctx(val), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 249); goto error; } while (0); |
250 | |
251 | aff = isl_aff_alloc(isl_local_space_copy(ls)); |
252 | if (!aff) |
253 | goto error; |
254 | |
255 | isl_seq_clr(aff->v->el + 2, aff->v->size - 2); |
256 | isl_int_set(aff->v->el[1], val->n)isl_sioimath_set((aff->v->el[1]), *(val->n)); |
257 | isl_int_set(aff->v->el[0], val->d)isl_sioimath_set((aff->v->el[0]), *(val->d)); |
258 | |
259 | isl_local_space_free(ls); |
260 | isl_val_free(val); |
261 | return aff; |
262 | error: |
263 | isl_local_space_free(ls); |
264 | isl_val_free(val); |
265 | return NULL((void*)0); |
266 | } |
267 | |
268 | /* Return an affine expression that is equal to "val" on domain space "space". |
269 | */ |
270 | __isl_give isl_aff *isl_aff_val_on_domain_space(__isl_take isl_space *space, |
271 | __isl_take isl_val *val) |
272 | { |
273 | return isl_aff_val_on_domain(isl_local_space_from_space(space), val); |
274 | } |
275 | |
276 | /* Return an affine expression that is equal to the specified dimension |
277 | * in "ls". |
278 | */ |
279 | __isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls, |
280 | enum isl_dim_type type, unsigned pos) |
281 | { |
282 | isl_space *space; |
283 | isl_aff *aff; |
284 | |
285 | if (!ls) |
286 | return NULL((void*)0); |
287 | |
288 | space = isl_local_space_get_space(ls); |
289 | if (!space) |
290 | goto error; |
291 | if (isl_space_is_map(space)) |
292 | isl_die(isl_space_get_ctx(space), isl_error_invalid,do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "expecting (parameter) set space", "polly/lib/External/isl/isl_aff.c" , 293); goto error; } while (0) |
293 | "expecting (parameter) set space", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "expecting (parameter) set space", "polly/lib/External/isl/isl_aff.c" , 293); goto error; } while (0); |
294 | if (isl_local_space_check_range(ls, type, pos, 1) < 0) |
295 | goto error; |
296 | |
297 | isl_space_free(space); |
298 | aff = isl_aff_alloc(ls); |
299 | if (!aff) |
300 | return NULL((void*)0); |
301 | |
302 | pos += isl_local_space_offset(aff->ls, type); |
303 | |
304 | isl_int_set_si(aff->v->el[0], 1)isl_sioimath_set_si((aff->v->el[0]), 1); |
305 | isl_seq_clr(aff->v->el + 1, aff->v->size - 1); |
306 | isl_int_set_si(aff->v->el[1 + pos], 1)isl_sioimath_set_si((aff->v->el[1 + pos]), 1); |
307 | |
308 | return aff; |
309 | error: |
310 | isl_local_space_free(ls); |
311 | isl_space_free(space); |
312 | return NULL((void*)0); |
313 | } |
314 | |
315 | /* Return a piecewise affine expression that is equal to |
316 | * the specified dimension in "ls". |
317 | */ |
318 | __isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls, |
319 | enum isl_dim_type type, unsigned pos) |
320 | { |
321 | return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos)); |
322 | } |
323 | |
324 | /* Return an affine expression that is equal to the parameter |
325 | * in the domain space "space" with identifier "id". |
326 | */ |
327 | __isl_give isl_aff *isl_aff_param_on_domain_space_id( |
328 | __isl_take isl_space *space, __isl_take isl_id *id) |
329 | { |
330 | int pos; |
331 | isl_local_space *ls; |
332 | |
333 | if (!space || !id) |
334 | goto error; |
335 | pos = isl_space_find_dim_by_id(space, isl_dim_param, id); |
336 | if (pos < 0) |
337 | isl_die(isl_space_get_ctx(space), isl_error_invalid,do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "parameter not found in space", "polly/lib/External/isl/isl_aff.c" , 338); goto error; } while (0) |
338 | "parameter not found in space", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "parameter not found in space", "polly/lib/External/isl/isl_aff.c" , 338); goto error; } while (0); |
339 | isl_id_free(id); |
340 | ls = isl_local_space_from_space(space); |
341 | return isl_aff_var_on_domain(ls, isl_dim_param, pos); |
342 | error: |
343 | isl_space_free(space); |
344 | isl_id_free(id); |
345 | return NULL((void*)0); |
346 | } |
347 | |
348 | /* This function performs the same operation as |
349 | * isl_aff_param_on_domain_space_id, |
350 | * but is considered as a function on an isl_space when exported. |
351 | */ |
352 | __isl_give isl_aff *isl_space_param_aff_on_domain_id( |
353 | __isl_take isl_space *space, __isl_take isl_id *id) |
354 | { |
355 | return isl_aff_param_on_domain_space_id(space, id); |
356 | } |
357 | |
358 | __isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff) |
359 | { |
360 | if (!aff) |
361 | return NULL((void*)0); |
362 | |
363 | if (--aff->ref > 0) |
364 | return NULL((void*)0); |
365 | |
366 | isl_local_space_free(aff->ls); |
367 | isl_vec_free(aff->v); |
368 | |
369 | free(aff); |
370 | |
371 | return NULL((void*)0); |
372 | } |
373 | |
374 | isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff) |
375 | { |
376 | return aff ? isl_local_space_get_ctx(aff->ls) : NULL((void*)0); |
377 | } |
378 | |
379 | /* Return a hash value that digests "aff". |
380 | */ |
381 | uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff) |
382 | { |
383 | uint32_t hash, ls_hash, v_hash; |
384 | |
385 | if (!aff) |
386 | return 0; |
387 | |
388 | hash = isl_hash_init()(2166136261u); |
389 | ls_hash = isl_local_space_get_hash(aff->ls); |
390 | isl_hash_hash(hash, ls_hash)do { do { hash *= 16777619; hash ^= (ls_hash) & 0xFF; } while (0); do { hash *= 16777619; hash ^= ((ls_hash) >> 8) & 0xFF; } while(0); do { hash *= 16777619; hash ^= ((ls_hash) >> 16) & 0xFF; } while(0); do { hash *= 16777619; hash ^= ( (ls_hash) >> 24) & 0xFF; } while(0); } while(0); |
391 | v_hash = isl_vec_get_hash(aff->v); |
392 | isl_hash_hash(hash, v_hash)do { do { hash *= 16777619; hash ^= (v_hash) & 0xFF; } while (0); do { hash *= 16777619; hash ^= ((v_hash) >> 8) & 0xFF; } while(0); do { hash *= 16777619; hash ^= ((v_hash) >> 16) & 0xFF; } while(0); do { hash *= 16777619; hash ^= ( (v_hash) >> 24) & 0xFF; } while(0); } while(0); |
393 | |
394 | return hash; |
395 | } |
396 | |
397 | /* Return the domain local space of "aff". |
398 | */ |
399 | static __isl_keep isl_local_space *isl_aff_peek_domain_local_space( |
400 | __isl_keep isl_aff *aff) |
401 | { |
402 | return aff ? aff->ls : NULL((void*)0); |
403 | } |
404 | |
405 | /* Return the number of variables of the given type in the domain of "aff". |
406 | */ |
407 | isl_size isl_aff_domain_dim(__isl_keep isl_aff *aff, enum isl_dim_type type) |
408 | { |
409 | isl_local_space *ls; |
410 | |
411 | ls = isl_aff_peek_domain_local_space(aff); |
412 | return isl_local_space_dim(ls, type); |
413 | } |
414 | |
415 | /* Externally, an isl_aff has a map space, but internally, the |
416 | * ls field corresponds to the domain of that space. |
417 | */ |
418 | isl_size isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type) |
419 | { |
420 | if (!aff) |
421 | return isl_size_error((int) -1); |
422 | if (type == isl_dim_out) |
423 | return 1; |
424 | if (type == isl_dim_in) |
425 | type = isl_dim_set; |
426 | return isl_aff_domain_dim(aff, type); |
427 | } |
428 | |
429 | /* Return the offset of the first coefficient of type "type" in |
430 | * the domain of "aff". |
431 | */ |
432 | isl_size isl_aff_domain_offset(__isl_keep isl_aff *aff, enum isl_dim_type type) |
433 | { |
434 | isl_local_space *ls; |
435 | |
436 | ls = isl_aff_peek_domain_local_space(aff); |
437 | return isl_local_space_offset(ls, type); |
438 | } |
439 | |
440 | /* Return the position of the dimension of the given type and name |
441 | * in "aff". |
442 | * Return -1 if no such dimension can be found. |
443 | */ |
444 | int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type, |
445 | const char *name) |
446 | { |
447 | if (!aff) |
448 | return -1; |
449 | if (type == isl_dim_out) |
450 | return -1; |
451 | if (type == isl_dim_in) |
452 | type = isl_dim_set; |
453 | return isl_local_space_find_dim_by_name(aff->ls, type, name); |
454 | } |
455 | |
456 | /* Return the domain space of "aff". |
457 | */ |
458 | static __isl_keep isl_space *isl_aff_peek_domain_space(__isl_keep isl_aff *aff) |
459 | { |
460 | return aff ? isl_local_space_peek_space(aff->ls) : NULL((void*)0); |
461 | } |
462 | |
463 | __isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff) |
464 | { |
465 | return isl_space_copy(isl_aff_peek_domain_space(aff)); |
466 | } |
467 | |
468 | __isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff) |
469 | { |
470 | isl_space *space; |
471 | if (!aff) |
472 | return NULL((void*)0); |
473 | space = isl_local_space_get_space(aff->ls); |
474 | space = isl_space_from_domain(space); |
475 | space = isl_space_add_dims(space, isl_dim_out, 1); |
476 | return space; |
477 | } |
478 | |
479 | /* Return a copy of the domain space of "aff". |
480 | */ |
481 | __isl_give isl_local_space *isl_aff_get_domain_local_space( |
482 | __isl_keep isl_aff *aff) |
483 | { |
484 | return isl_local_space_copy(isl_aff_peek_domain_local_space(aff)); |
485 | } |
486 | |
487 | __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff) |
488 | { |
489 | isl_local_space *ls; |
490 | if (!aff) |
491 | return NULL((void*)0); |
492 | ls = isl_local_space_copy(aff->ls); |
493 | ls = isl_local_space_from_domain(ls); |
494 | ls = isl_local_space_add_dims(ls, isl_dim_out, 1); |
495 | return ls; |
496 | } |
497 | |
498 | /* Return the local space of the domain of "aff". |
499 | * This may be either a copy or the local space itself |
500 | * if there is only one reference to "aff". |
501 | * This allows the local space to be modified inplace |
502 | * if both the expression and its local space have only a single reference. |
503 | * The caller is not allowed to modify "aff" between this call and |
504 | * a subsequent call to isl_aff_restore_domain_local_space. |
505 | * The only exception is that isl_aff_free can be called instead. |
506 | */ |
507 | __isl_give isl_local_space *isl_aff_take_domain_local_space( |
508 | __isl_keep isl_aff *aff) |
509 | { |
510 | isl_local_space *ls; |
511 | |
512 | if (!aff) |
513 | return NULL((void*)0); |
514 | if (aff->ref != 1) |
515 | return isl_aff_get_domain_local_space(aff); |
516 | ls = aff->ls; |
517 | aff->ls = NULL((void*)0); |
518 | return ls; |
519 | } |
520 | |
521 | /* Set the local space of the domain of "aff" to "ls", |
522 | * where the local space of "aff" may be missing |
523 | * due to a preceding call to isl_aff_take_domain_local_space. |
524 | * However, in this case, "aff" only has a single reference and |
525 | * then the call to isl_aff_cow has no effect. |
526 | */ |
527 | __isl_give isl_aff *isl_aff_restore_domain_local_space( |
528 | __isl_keep isl_aff *aff, __isl_take isl_local_space *ls) |
529 | { |
530 | if (!aff || !ls) |
531 | goto error; |
532 | |
533 | if (aff->ls == ls) { |
534 | isl_local_space_free(ls); |
535 | return aff; |
536 | } |
537 | |
538 | aff = isl_aff_cow(aff); |
539 | if (!aff) |
540 | goto error; |
541 | isl_local_space_free(aff->ls); |
542 | aff->ls = ls; |
543 | |
544 | return aff; |
545 | error: |
546 | isl_aff_free(aff); |
547 | isl_local_space_free(ls); |
548 | return NULL((void*)0); |
549 | } |
550 | |
551 | /* Externally, an isl_aff has a map space, but internally, the |
552 | * ls field corresponds to the domain of that space. |
553 | */ |
554 | const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff, |
555 | enum isl_dim_type type, unsigned pos) |
556 | { |
557 | if (!aff) |
558 | return NULL((void*)0); |
559 | if (type == isl_dim_out) |
560 | return NULL((void*)0); |
561 | if (type == isl_dim_in) |
562 | type = isl_dim_set; |
563 | return isl_local_space_get_dim_name(aff->ls, type, pos); |
564 | } |
565 | |
566 | __isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff, |
567 | __isl_take isl_space *space) |
568 | { |
569 | aff = isl_aff_cow(aff); |
570 | if (!aff || !space) |
571 | goto error; |
572 | |
573 | aff->ls = isl_local_space_reset_space(aff->ls, space); |
574 | if (!aff->ls) |
575 | return isl_aff_free(aff); |
576 | |
577 | return aff; |
578 | error: |
579 | isl_aff_free(aff); |
580 | isl_space_free(space); |
581 | return NULL((void*)0); |
582 | } |
583 | |
584 | /* Reset the space of "aff". This function is called from isl_pw_templ.c |
585 | * and doesn't know if the space of an element object is represented |
586 | * directly or through its domain. It therefore passes along both. |
587 | */ |
588 | __isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff, |
589 | __isl_take isl_space *space, __isl_take isl_space *domain) |
590 | { |
591 | isl_space_free(space); |
592 | return isl_aff_reset_domain_space(aff, domain); |
593 | } |
594 | |
595 | /* Reorder the coefficients of the affine expression based |
596 | * on the given reordering. |
597 | * The reordering r is assumed to have been extended with the local |
598 | * variables. |
599 | */ |
600 | static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec, |
601 | __isl_take isl_reordering *r, int n_div) |
602 | { |
603 | isl_space *space; |
604 | isl_vec *res; |
605 | isl_size dim; |
606 | int i; |
607 | |
608 | if (!vec || !r) |
609 | goto error; |
610 | |
611 | space = isl_reordering_peek_space(r); |
612 | dim = isl_space_dim(space, isl_dim_all); |
613 | if (dim < 0) |
614 | goto error; |
615 | res = isl_vec_alloc(vec->ctx, 2 + dim + n_div); |
616 | if (!res) |
617 | goto error; |
618 | isl_seq_cpy(res->el, vec->el, 2); |
619 | isl_seq_clr(res->el + 2, res->size - 2); |
620 | for (i = 0; i < r->len; ++i) |
621 | isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i])isl_sioimath_set((res->el[2 + r->pos[i]]), *(vec->el [2 + i])); |
622 | |
623 | isl_reordering_free(r); |
624 | isl_vec_free(vec); |
625 | return res; |
626 | error: |
627 | isl_vec_free(vec); |
628 | isl_reordering_free(r); |
629 | return NULL((void*)0); |
630 | } |
631 | |
632 | /* Reorder the dimensions of the domain of "aff" according |
633 | * to the given reordering. |
634 | */ |
635 | __isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff, |
636 | __isl_take isl_reordering *r) |
637 | { |
638 | aff = isl_aff_cow(aff); |
639 | if (!aff) |
640 | goto error; |
641 | |
642 | r = isl_reordering_extend(r, aff->ls->div->n_row); |
643 | aff->v = vec_reorder(aff->v, isl_reordering_copy(r), |
644 | aff->ls->div->n_row); |
645 | aff->ls = isl_local_space_realign(aff->ls, r); |
646 | |
647 | if (!aff->v || !aff->ls) |
648 | return isl_aff_free(aff); |
649 | |
650 | return aff; |
651 | error: |
652 | isl_aff_free(aff); |
653 | isl_reordering_free(r); |
654 | return NULL((void*)0); |
655 | } |
656 | |
657 | __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff, |
658 | __isl_take isl_space *model) |
659 | { |
660 | isl_bool equal_params; |
661 | |
662 | if (!aff || !model) |
663 | goto error; |
664 | |
665 | equal_params = isl_space_has_equal_params(aff->ls->dim, model); |
666 | if (equal_params < 0) |
667 | goto error; |
668 | if (!equal_params) { |
669 | isl_reordering *exp; |
670 | |
671 | exp = isl_parameter_alignment_reordering(aff->ls->dim, model); |
672 | exp = isl_reordering_extend_space(exp, |
673 | isl_aff_get_domain_space(aff)); |
674 | aff = isl_aff_realign_domain(aff, exp); |
675 | } |
676 | |
677 | isl_space_free(model); |
678 | return aff; |
679 | error: |
680 | isl_space_free(model); |
681 | isl_aff_free(aff); |
682 | return NULL((void*)0); |
683 | } |
684 | |
685 | #undef TYPEisl_multi_union_pw_aff |
686 | #define TYPEisl_multi_union_pw_aff isl_aff |
687 | #include "isl_unbind_params_templ.c" |
688 | |
689 | /* Is "aff" obviously equal to zero? |
690 | * |
691 | * If the denominator is zero, then "aff" is not equal to zero. |
692 | */ |
693 | isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff) |
694 | { |
695 | int pos; |
696 | |
697 | if (!aff) |
698 | return isl_bool_error; |
699 | |
700 | if (isl_int_is_zero(aff->v->el[0])(isl_sioimath_sgn(*(aff->v->el[0])) == 0)) |
701 | return isl_bool_false; |
702 | pos = isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1); |
703 | return isl_bool_ok(pos < 0); |
704 | } |
705 | |
706 | /* Does "aff" represent NaN? |
707 | */ |
708 | isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff) |
709 | { |
710 | if (!aff) |
711 | return isl_bool_error; |
712 | |
713 | return isl_bool_ok(isl_seq_first_non_zero(aff->v->el, 2) < 0); |
714 | } |
715 | |
716 | /* Are "aff1" and "aff2" obviously equal? |
717 | * |
718 | * NaN is not equal to anything, not even to another NaN. |
719 | */ |
720 | isl_bool isl_aff_plain_is_equal(__isl_keep isl_aff *aff1, |
721 | __isl_keep isl_aff *aff2) |
722 | { |
723 | isl_bool equal; |
724 | |
725 | if (!aff1 || !aff2) |
726 | return isl_bool_error; |
727 | |
728 | if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2)) |
729 | return isl_bool_false; |
730 | |
731 | equal = isl_local_space_is_equal(aff1->ls, aff2->ls); |
732 | if (equal < 0 || !equal) |
733 | return equal; |
734 | |
735 | return isl_vec_is_equal(aff1->v, aff2->v); |
736 | } |
737 | |
738 | /* Return the common denominator of "aff" in "v". |
739 | * |
740 | * We cannot return anything meaningful in case of a NaN. |
741 | */ |
742 | isl_stat isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v) |
743 | { |
744 | if (!aff) |
745 | return isl_stat_error; |
746 | if (isl_aff_is_nan(aff)) |
747 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot get denominator of NaN", "polly/lib/External/isl/isl_aff.c" , 748); return isl_stat_error; } while (0) |
748 | "cannot get denominator of NaN", return isl_stat_error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot get denominator of NaN", "polly/lib/External/isl/isl_aff.c" , 748); return isl_stat_error; } while (0); |
749 | isl_int_set(*v, aff->v->el[0])isl_sioimath_set((*v), *(aff->v->el[0])); |
750 | return isl_stat_ok; |
751 | } |
752 | |
753 | /* Return the common denominator of "aff". |
754 | */ |
755 | __isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff) |
756 | { |
757 | isl_ctx *ctx; |
758 | |
759 | if (!aff) |
760 | return NULL((void*)0); |
761 | |
762 | ctx = isl_aff_get_ctx(aff); |
763 | if (isl_aff_is_nan(aff)) |
764 | return isl_val_nan(ctx); |
765 | return isl_val_int_from_isl_int(ctx, aff->v->el[0]); |
766 | } |
767 | |
768 | /* Return the constant term of "aff". |
769 | */ |
770 | __isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff) |
771 | { |
772 | isl_ctx *ctx; |
773 | isl_val *v; |
774 | |
775 | if (!aff) |
776 | return NULL((void*)0); |
777 | |
778 | ctx = isl_aff_get_ctx(aff); |
779 | if (isl_aff_is_nan(aff)) |
780 | return isl_val_nan(ctx); |
781 | v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]); |
782 | return isl_val_normalize(v); |
783 | } |
784 | |
785 | /* Return the coefficient of the variable of type "type" at position "pos" |
786 | * of "aff". |
787 | */ |
788 | __isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff, |
789 | enum isl_dim_type type, int pos) |
790 | { |
791 | isl_ctx *ctx; |
792 | isl_val *v; |
793 | |
794 | if (!aff) |
795 | return NULL((void*)0); |
796 | |
797 | ctx = isl_aff_get_ctx(aff); |
798 | if (type == isl_dim_out) |
799 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 801); return ((void*)0) ; } while (0) |
800 | "output/set dimension does not have a coefficient",do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 801); return ((void*)0) ; } while (0) |
801 | return NULL)do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 801); return ((void*)0) ; } while (0); |
802 | if (type == isl_dim_in) |
803 | type = isl_dim_set; |
804 | |
805 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
806 | return NULL((void*)0); |
807 | |
808 | if (isl_aff_is_nan(aff)) |
809 | return isl_val_nan(ctx); |
810 | pos += isl_local_space_offset(aff->ls, type); |
811 | v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]); |
812 | return isl_val_normalize(v); |
813 | } |
814 | |
815 | /* Return the sign of the coefficient of the variable of type "type" |
816 | * at position "pos" of "aff". |
817 | */ |
818 | int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type, |
819 | int pos) |
820 | { |
821 | isl_ctx *ctx; |
822 | |
823 | if (!aff) |
824 | return 0; |
825 | |
826 | ctx = isl_aff_get_ctx(aff); |
827 | if (type == isl_dim_out) |
828 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 830); return 0; } while (0) |
829 | "output/set dimension does not have a coefficient",do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 830); return 0; } while (0) |
830 | return 0)do { isl_handle_error(ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 830); return 0; } while (0); |
831 | if (type == isl_dim_in) |
832 | type = isl_dim_set; |
833 | |
834 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
835 | return 0; |
836 | |
837 | pos += isl_local_space_offset(aff->ls, type); |
838 | return isl_int_sgn(aff->v->el[1 + pos])isl_sioimath_sgn(*(aff->v->el[1 + pos])); |
839 | } |
840 | |
841 | /* Replace the numerator of the constant term of "aff" by "v". |
842 | * |
843 | * A NaN is unaffected by this operation. |
844 | */ |
845 | __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v) |
846 | { |
847 | if (!aff) |
848 | return NULL((void*)0); |
849 | if (isl_aff_is_nan(aff)) |
850 | return aff; |
851 | aff = isl_aff_cow(aff); |
852 | if (!aff) |
853 | return NULL((void*)0); |
854 | |
855 | aff->v = isl_vec_cow(aff->v); |
856 | if (!aff->v) |
857 | return isl_aff_free(aff); |
858 | |
859 | isl_int_set(aff->v->el[1], v)isl_sioimath_set((aff->v->el[1]), *(v)); |
860 | |
861 | return aff; |
862 | } |
863 | |
864 | /* Replace the constant term of "aff" by "v". |
865 | * |
866 | * A NaN is unaffected by this operation. |
867 | */ |
868 | __isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff, |
869 | __isl_take isl_val *v) |
870 | { |
871 | if (!aff || !v) |
872 | goto error; |
873 | |
874 | if (isl_aff_is_nan(aff)) { |
875 | isl_val_free(v); |
876 | return aff; |
877 | } |
878 | |
879 | if (!isl_val_is_rat(v)) |
880 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 881); goto error; } while (0) |
881 | "expecting rational value", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 881); goto error; } while (0); |
882 | |
883 | if (isl_int_eq(aff->v->el[1], v->n)(isl_sioimath_cmp(*(aff->v->el[1]), *(v->n)) == 0) && |
884 | isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
885 | isl_val_free(v); |
886 | return aff; |
887 | } |
888 | |
889 | aff = isl_aff_cow(aff); |
890 | if (!aff) |
891 | goto error; |
892 | aff->v = isl_vec_cow(aff->v); |
893 | if (!aff->v) |
894 | goto error; |
895 | |
896 | if (isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
897 | isl_int_set(aff->v->el[1], v->n)isl_sioimath_set((aff->v->el[1]), *(v->n)); |
898 | } else if (isl_int_is_one(v->d)(isl_sioimath_cmp_si(*(v->d), 1) == 0)) { |
899 | isl_int_mul(aff->v->el[1], aff->v->el[0], v->n)isl_sioimath_mul((aff->v->el[1]), *(aff->v->el[0] ), *(v->n)); |
900 | } else { |
901 | isl_seq_scale(aff->v->el + 1, |
902 | aff->v->el + 1, v->d, aff->v->size - 1); |
903 | isl_int_mul(aff->v->el[1], aff->v->el[0], v->n)isl_sioimath_mul((aff->v->el[1]), *(aff->v->el[0] ), *(v->n)); |
904 | isl_int_mul(aff->v->el[0], aff->v->el[0], v->d)isl_sioimath_mul((aff->v->el[0]), *(aff->v->el[0] ), *(v->d)); |
905 | aff->v = isl_vec_normalize(aff->v); |
906 | if (!aff->v) |
907 | goto error; |
908 | } |
909 | |
910 | isl_val_free(v); |
911 | return aff; |
912 | error: |
913 | isl_aff_free(aff); |
914 | isl_val_free(v); |
915 | return NULL((void*)0); |
916 | } |
917 | |
918 | /* Add "v" to the constant term of "aff". |
919 | * |
920 | * A NaN is unaffected by this operation. |
921 | */ |
922 | __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v) |
923 | { |
924 | if (isl_int_is_zero(v)(isl_sioimath_sgn(*(v)) == 0)) |
925 | return aff; |
926 | |
927 | if (!aff) |
928 | return NULL((void*)0); |
929 | if (isl_aff_is_nan(aff)) |
930 | return aff; |
931 | aff = isl_aff_cow(aff); |
932 | if (!aff) |
933 | return NULL((void*)0); |
934 | |
935 | aff->v = isl_vec_cow(aff->v); |
936 | if (!aff->v) |
937 | return isl_aff_free(aff); |
938 | |
939 | isl_int_addmul(aff->v->el[1], aff->v->el[0], v)isl_sioimath_addmul((aff->v->el[1]), *(aff->v->el [0]), *(v)); |
940 | |
941 | return aff; |
942 | } |
943 | |
944 | /* Add "v" to the constant term of "aff", |
945 | * in case "aff" is a rational expression. |
946 | */ |
947 | static __isl_give isl_aff *isl_aff_add_rat_constant_val(__isl_take isl_aff *aff, |
948 | __isl_take isl_val *v) |
949 | { |
950 | aff = isl_aff_cow(aff); |
951 | if (!aff) |
952 | goto error; |
953 | |
954 | aff->v = isl_vec_cow(aff->v); |
955 | if (!aff->v) |
956 | goto error; |
957 | |
958 | if (isl_int_is_one(v->d)(isl_sioimath_cmp_si(*(v->d), 1) == 0)) { |
959 | isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n)isl_sioimath_addmul((aff->v->el[1]), *(aff->v->el [0]), *(v->n)); |
960 | } else if (isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
961 | isl_int_add(aff->v->el[1], aff->v->el[1], v->n)isl_sioimath_add((aff->v->el[1]), *(aff->v->el[1] ), *(v->n)); |
962 | aff->v = isl_vec_normalize(aff->v); |
963 | if (!aff->v) |
964 | goto error; |
965 | } else { |
966 | isl_seq_scale(aff->v->el + 1, |
967 | aff->v->el + 1, v->d, aff->v->size - 1); |
968 | isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n)isl_sioimath_addmul((aff->v->el[1]), *(aff->v->el [0]), *(v->n)); |
969 | isl_int_mul(aff->v->el[0], aff->v->el[0], v->d)isl_sioimath_mul((aff->v->el[0]), *(aff->v->el[0] ), *(v->d)); |
970 | aff->v = isl_vec_normalize(aff->v); |
971 | if (!aff->v) |
972 | goto error; |
973 | } |
974 | |
975 | isl_val_free(v); |
976 | return aff; |
977 | error: |
978 | isl_aff_free(aff); |
979 | isl_val_free(v); |
980 | return NULL((void*)0); |
981 | } |
982 | |
983 | /* Return the first argument and free the second. |
984 | */ |
985 | static __isl_give isl_aff *pick_free(__isl_take isl_aff *aff, |
986 | __isl_take isl_val *v) |
987 | { |
988 | isl_val_free(v); |
989 | return aff; |
990 | } |
991 | |
992 | /* Replace the first argument by NaN and free the second argument. |
993 | */ |
994 | static __isl_give isl_aff *set_nan_free_val(__isl_take isl_aff *aff, |
995 | __isl_take isl_val *v) |
996 | { |
997 | isl_val_free(v); |
998 | return isl_aff_set_nan(aff); |
999 | } |
1000 | |
1001 | /* Add "v" to the constant term of "aff". |
1002 | * |
1003 | * A NaN is unaffected by this operation. |
1004 | * Conversely, adding a NaN turns "aff" into a NaN. |
1005 | */ |
1006 | __isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff, |
1007 | __isl_take isl_val *v) |
1008 | { |
1009 | isl_bool is_nan, is_zero, is_rat; |
1010 | |
1011 | is_nan = isl_aff_is_nan(aff); |
1012 | is_zero = isl_val_is_zero(v); |
1013 | if (is_nan < 0 || is_zero < 0) |
1014 | goto error; |
1015 | if (is_nan || is_zero) |
1016 | return pick_free(aff, v); |
1017 | |
1018 | is_nan = isl_val_is_nan(v); |
1019 | is_rat = isl_val_is_rat(v); |
1020 | if (is_nan < 0 || is_rat < 0) |
1021 | goto error; |
1022 | if (is_nan) |
1023 | return set_nan_free_val(aff, v); |
1024 | if (!is_rat) |
1025 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value or NaN", "polly/lib/External/isl/isl_aff.c" , 1026); goto error; } while (0) |
1026 | "expecting rational value or NaN", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value or NaN", "polly/lib/External/isl/isl_aff.c" , 1026); goto error; } while (0); |
1027 | |
1028 | return isl_aff_add_rat_constant_val(aff, v); |
1029 | error: |
1030 | isl_aff_free(aff); |
1031 | isl_val_free(v); |
1032 | return NULL((void*)0); |
1033 | } |
1034 | |
1035 | __isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v) |
1036 | { |
1037 | isl_int t; |
1038 | |
1039 | isl_int_init(t)isl_sioimath_init((t)); |
1040 | isl_int_set_si(t, v)isl_sioimath_set_si((t), v); |
1041 | aff = isl_aff_add_constant(aff, t); |
1042 | isl_int_clear(t)isl_sioimath_clear((t)); |
1043 | |
1044 | return aff; |
1045 | } |
1046 | |
1047 | /* Add "v" to the numerator of the constant term of "aff". |
1048 | * |
1049 | * A NaN is unaffected by this operation. |
1050 | */ |
1051 | __isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v) |
1052 | { |
1053 | if (isl_int_is_zero(v)(isl_sioimath_sgn(*(v)) == 0)) |
1054 | return aff; |
1055 | |
1056 | if (!aff) |
1057 | return NULL((void*)0); |
1058 | if (isl_aff_is_nan(aff)) |
1059 | return aff; |
1060 | aff = isl_aff_cow(aff); |
1061 | if (!aff) |
1062 | return NULL((void*)0); |
1063 | |
1064 | aff->v = isl_vec_cow(aff->v); |
1065 | if (!aff->v) |
1066 | return isl_aff_free(aff); |
1067 | |
1068 | isl_int_add(aff->v->el[1], aff->v->el[1], v)isl_sioimath_add((aff->v->el[1]), *(aff->v->el[1] ), *(v)); |
1069 | |
1070 | return aff; |
1071 | } |
1072 | |
1073 | /* Add "v" to the numerator of the constant term of "aff". |
1074 | * |
1075 | * A NaN is unaffected by this operation. |
1076 | */ |
1077 | __isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v) |
1078 | { |
1079 | isl_int t; |
1080 | |
1081 | if (v == 0) |
1082 | return aff; |
1083 | |
1084 | isl_int_init(t)isl_sioimath_init((t)); |
1085 | isl_int_set_si(t, v)isl_sioimath_set_si((t), v); |
1086 | aff = isl_aff_add_constant_num(aff, t); |
1087 | isl_int_clear(t)isl_sioimath_clear((t)); |
1088 | |
1089 | return aff; |
1090 | } |
1091 | |
1092 | /* Replace the numerator of the constant term of "aff" by "v". |
1093 | * |
1094 | * A NaN is unaffected by this operation. |
1095 | */ |
1096 | __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v) |
1097 | { |
1098 | if (!aff) |
1099 | return NULL((void*)0); |
1100 | if (isl_aff_is_nan(aff)) |
1101 | return aff; |
1102 | aff = isl_aff_cow(aff); |
1103 | if (!aff) |
1104 | return NULL((void*)0); |
1105 | |
1106 | aff->v = isl_vec_cow(aff->v); |
1107 | if (!aff->v) |
1108 | return isl_aff_free(aff); |
1109 | |
1110 | isl_int_set_si(aff->v->el[1], v)isl_sioimath_set_si((aff->v->el[1]), v); |
1111 | |
1112 | return aff; |
1113 | } |
1114 | |
1115 | /* Replace the numerator of the coefficient of the variable of type "type" |
1116 | * at position "pos" of "aff" by "v". |
1117 | * |
1118 | * A NaN is unaffected by this operation. |
1119 | */ |
1120 | __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff, |
1121 | enum isl_dim_type type, int pos, isl_int v) |
1122 | { |
1123 | if (!aff) |
1124 | return NULL((void*)0); |
1125 | |
1126 | if (type == isl_dim_out) |
1127 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1129); return isl_aff_free (aff); } while (0) |
1128 | "output/set dimension does not have a coefficient",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1129); return isl_aff_free (aff); } while (0) |
1129 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1129); return isl_aff_free (aff); } while (0); |
1130 | if (type == isl_dim_in) |
1131 | type = isl_dim_set; |
1132 | |
1133 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
1134 | return isl_aff_free(aff); |
1135 | |
1136 | if (isl_aff_is_nan(aff)) |
1137 | return aff; |
1138 | aff = isl_aff_cow(aff); |
1139 | if (!aff) |
1140 | return NULL((void*)0); |
1141 | |
1142 | aff->v = isl_vec_cow(aff->v); |
1143 | if (!aff->v) |
1144 | return isl_aff_free(aff); |
1145 | |
1146 | pos += isl_local_space_offset(aff->ls, type); |
1147 | isl_int_set(aff->v->el[1 + pos], v)isl_sioimath_set((aff->v->el[1 + pos]), *(v)); |
1148 | |
1149 | return aff; |
1150 | } |
1151 | |
1152 | /* Replace the numerator of the coefficient of the variable of type "type" |
1153 | * at position "pos" of "aff" by "v". |
1154 | * |
1155 | * A NaN is unaffected by this operation. |
1156 | */ |
1157 | __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff, |
1158 | enum isl_dim_type type, int pos, int v) |
1159 | { |
1160 | if (!aff) |
1161 | return NULL((void*)0); |
1162 | |
1163 | if (type == isl_dim_out) |
1164 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1166); return isl_aff_free (aff); } while (0) |
1165 | "output/set dimension does not have a coefficient",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1166); return isl_aff_free (aff); } while (0) |
1166 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1166); return isl_aff_free (aff); } while (0); |
1167 | if (type == isl_dim_in) |
1168 | type = isl_dim_set; |
1169 | |
1170 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
1171 | return isl_aff_free(aff); |
1172 | |
1173 | if (isl_aff_is_nan(aff)) |
1174 | return aff; |
1175 | pos += isl_local_space_offset(aff->ls, type); |
1176 | if (isl_int_cmp_si(aff->v->el[1 + pos], v)isl_sioimath_cmp_si(*(aff->v->el[1 + pos]), v) == 0) |
1177 | return aff; |
1178 | |
1179 | aff = isl_aff_cow(aff); |
1180 | if (!aff) |
1181 | return NULL((void*)0); |
1182 | |
1183 | aff->v = isl_vec_cow(aff->v); |
1184 | if (!aff->v) |
1185 | return isl_aff_free(aff); |
1186 | |
1187 | isl_int_set_si(aff->v->el[1 + pos], v)isl_sioimath_set_si((aff->v->el[1 + pos]), v); |
1188 | |
1189 | return aff; |
1190 | } |
1191 | |
1192 | /* Replace the coefficient of the variable of type "type" at position "pos" |
1193 | * of "aff" by "v". |
1194 | * |
1195 | * A NaN is unaffected by this operation. |
1196 | */ |
1197 | __isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff, |
1198 | enum isl_dim_type type, int pos, __isl_take isl_val *v) |
1199 | { |
1200 | if (!aff || !v) |
1201 | goto error; |
1202 | |
1203 | if (type == isl_dim_out) |
1204 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1206); goto error; } while (0) |
1205 | "output/set dimension does not have a coefficient",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1206); goto error; } while (0) |
1206 | goto error)do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1206); goto error; } while (0); |
1207 | if (type == isl_dim_in) |
1208 | type = isl_dim_set; |
1209 | |
1210 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
1211 | return isl_aff_free(aff); |
1212 | |
1213 | if (isl_aff_is_nan(aff)) { |
1214 | isl_val_free(v); |
1215 | return aff; |
1216 | } |
1217 | if (!isl_val_is_rat(v)) |
1218 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 1219); goto error; } while (0) |
1219 | "expecting rational value", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 1219); goto error; } while (0); |
1220 | |
1221 | pos += isl_local_space_offset(aff->ls, type); |
1222 | if (isl_int_eq(aff->v->el[1 + pos], v->n)(isl_sioimath_cmp(*(aff->v->el[1 + pos]), *(v->n)) == 0) && |
1223 | isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
1224 | isl_val_free(v); |
1225 | return aff; |
1226 | } |
1227 | |
1228 | aff = isl_aff_cow(aff); |
1229 | if (!aff) |
1230 | goto error; |
1231 | aff->v = isl_vec_cow(aff->v); |
1232 | if (!aff->v) |
1233 | goto error; |
1234 | |
1235 | if (isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
1236 | isl_int_set(aff->v->el[1 + pos], v->n)isl_sioimath_set((aff->v->el[1 + pos]), *(v->n)); |
1237 | } else if (isl_int_is_one(v->d)(isl_sioimath_cmp_si(*(v->d), 1) == 0)) { |
1238 | isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n)isl_sioimath_mul((aff->v->el[1 + pos]), *(aff->v-> el[0]), *(v->n)); |
1239 | } else { |
1240 | isl_seq_scale(aff->v->el + 1, |
1241 | aff->v->el + 1, v->d, aff->v->size - 1); |
1242 | isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n)isl_sioimath_mul((aff->v->el[1 + pos]), *(aff->v-> el[0]), *(v->n)); |
1243 | isl_int_mul(aff->v->el[0], aff->v->el[0], v->d)isl_sioimath_mul((aff->v->el[0]), *(aff->v->el[0] ), *(v->d)); |
1244 | aff->v = isl_vec_normalize(aff->v); |
1245 | if (!aff->v) |
1246 | goto error; |
1247 | } |
1248 | |
1249 | isl_val_free(v); |
1250 | return aff; |
1251 | error: |
1252 | isl_aff_free(aff); |
1253 | isl_val_free(v); |
1254 | return NULL((void*)0); |
1255 | } |
1256 | |
1257 | /* Add "v" to the coefficient of the variable of type "type" |
1258 | * at position "pos" of "aff". |
1259 | * |
1260 | * A NaN is unaffected by this operation. |
1261 | */ |
1262 | __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff, |
1263 | enum isl_dim_type type, int pos, isl_int v) |
1264 | { |
1265 | if (!aff) |
1266 | return NULL((void*)0); |
1267 | |
1268 | if (type == isl_dim_out) |
1269 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1271); return isl_aff_free (aff); } while (0) |
1270 | "output/set dimension does not have a coefficient",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1271); return isl_aff_free (aff); } while (0) |
1271 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1271); return isl_aff_free (aff); } while (0); |
1272 | if (type == isl_dim_in) |
1273 | type = isl_dim_set; |
1274 | |
1275 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
1276 | return isl_aff_free(aff); |
1277 | |
1278 | if (isl_aff_is_nan(aff)) |
1279 | return aff; |
1280 | aff = isl_aff_cow(aff); |
1281 | if (!aff) |
1282 | return NULL((void*)0); |
1283 | |
1284 | aff->v = isl_vec_cow(aff->v); |
1285 | if (!aff->v) |
1286 | return isl_aff_free(aff); |
1287 | |
1288 | pos += isl_local_space_offset(aff->ls, type); |
1289 | isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v)isl_sioimath_addmul((aff->v->el[1 + pos]), *(aff->v-> el[0]), *(v)); |
1290 | |
1291 | return aff; |
1292 | } |
1293 | |
1294 | /* Add "v" to the coefficient of the variable of type "type" |
1295 | * at position "pos" of "aff". |
1296 | * |
1297 | * A NaN is unaffected by this operation. |
1298 | */ |
1299 | __isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff, |
1300 | enum isl_dim_type type, int pos, __isl_take isl_val *v) |
1301 | { |
1302 | if (!aff || !v) |
1303 | goto error; |
1304 | |
1305 | if (isl_val_is_zero(v)) { |
1306 | isl_val_free(v); |
1307 | return aff; |
1308 | } |
1309 | |
1310 | if (type == isl_dim_out) |
1311 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1313); goto error; } while (0) |
1312 | "output/set dimension does not have a coefficient",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1313); goto error; } while (0) |
1313 | goto error)do { isl_handle_error(aff->v->ctx, isl_error_invalid, "output/set dimension does not have a coefficient" , "polly/lib/External/isl/isl_aff.c", 1313); goto error; } while (0); |
1314 | if (type == isl_dim_in) |
1315 | type = isl_dim_set; |
1316 | |
1317 | if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) |
1318 | goto error; |
1319 | |
1320 | if (isl_aff_is_nan(aff)) { |
1321 | isl_val_free(v); |
1322 | return aff; |
1323 | } |
1324 | if (!isl_val_is_rat(v)) |
1325 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 1326); goto error; } while (0) |
1326 | "expecting rational value", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational value", "polly/lib/External/isl/isl_aff.c" , 1326); goto error; } while (0); |
1327 | |
1328 | aff = isl_aff_cow(aff); |
1329 | if (!aff) |
1330 | goto error; |
1331 | |
1332 | aff->v = isl_vec_cow(aff->v); |
1333 | if (!aff->v) |
1334 | goto error; |
1335 | |
1336 | pos += isl_local_space_offset(aff->ls, type); |
1337 | if (isl_int_is_one(v->d)(isl_sioimath_cmp_si(*(v->d), 1) == 0)) { |
1338 | isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n)isl_sioimath_addmul((aff->v->el[1 + pos]), *(aff->v-> el[0]), *(v->n)); |
1339 | } else if (isl_int_eq(aff->v->el[0], v->d)(isl_sioimath_cmp(*(aff->v->el[0]), *(v->d)) == 0)) { |
1340 | isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n)isl_sioimath_add((aff->v->el[1 + pos]), *(aff->v-> el[1 + pos]), *(v->n)); |
1341 | aff->v = isl_vec_normalize(aff->v); |
1342 | if (!aff->v) |
1343 | goto error; |
1344 | } else { |
1345 | isl_seq_scale(aff->v->el + 1, |
1346 | aff->v->el + 1, v->d, aff->v->size - 1); |
1347 | isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n)isl_sioimath_addmul((aff->v->el[1 + pos]), *(aff->v-> el[0]), *(v->n)); |
1348 | isl_int_mul(aff->v->el[0], aff->v->el[0], v->d)isl_sioimath_mul((aff->v->el[0]), *(aff->v->el[0] ), *(v->d)); |
1349 | aff->v = isl_vec_normalize(aff->v); |
1350 | if (!aff->v) |
1351 | goto error; |
1352 | } |
1353 | |
1354 | isl_val_free(v); |
1355 | return aff; |
1356 | error: |
1357 | isl_aff_free(aff); |
1358 | isl_val_free(v); |
1359 | return NULL((void*)0); |
1360 | } |
1361 | |
1362 | __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff, |
1363 | enum isl_dim_type type, int pos, int v) |
1364 | { |
1365 | isl_int t; |
1366 | |
1367 | isl_int_init(t)isl_sioimath_init((t)); |
1368 | isl_int_set_si(t, v)isl_sioimath_set_si((t), v); |
1369 | aff = isl_aff_add_coefficient(aff, type, pos, t); |
1370 | isl_int_clear(t)isl_sioimath_clear((t)); |
1371 | |
1372 | return aff; |
1373 | } |
1374 | |
1375 | __isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos) |
1376 | { |
1377 | if (!aff) |
1378 | return NULL((void*)0); |
1379 | |
1380 | return isl_local_space_get_div(aff->ls, pos); |
1381 | } |
1382 | |
1383 | /* Return the negation of "aff". |
1384 | * |
1385 | * As a special case, -NaN = NaN. |
1386 | */ |
1387 | __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff) |
1388 | { |
1389 | if (!aff) |
1390 | return NULL((void*)0); |
1391 | if (isl_aff_is_nan(aff)) |
1392 | return aff; |
1393 | aff = isl_aff_cow(aff); |
1394 | if (!aff) |
1395 | return NULL((void*)0); |
1396 | aff->v = isl_vec_cow(aff->v); |
1397 | if (!aff->v) |
1398 | return isl_aff_free(aff); |
1399 | |
1400 | isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1); |
1401 | |
1402 | return aff; |
1403 | } |
1404 | |
1405 | /* Remove divs from the local space that do not appear in the affine |
1406 | * expression. |
1407 | * We currently only remove divs at the end. |
1408 | * Some intermediate divs may also not appear directly in the affine |
1409 | * expression, but we would also need to check that no other divs are |
1410 | * defined in terms of them. |
1411 | */ |
1412 | __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff) |
1413 | { |
1414 | int pos; |
1415 | isl_size off; |
1416 | isl_size n; |
1417 | |
1418 | n = isl_aff_domain_dim(aff, isl_dim_div); |
1419 | off = isl_aff_domain_offset(aff, isl_dim_div); |
1420 | if (n < 0 || off < 0) |
1421 | return isl_aff_free(aff); |
1422 | |
1423 | pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1; |
1424 | if (pos == n) |
1425 | return aff; |
1426 | |
1427 | aff = isl_aff_cow(aff); |
1428 | if (!aff) |
1429 | return NULL((void*)0); |
1430 | |
1431 | aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos); |
1432 | aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos); |
1433 | if (!aff->ls || !aff->v) |
1434 | return isl_aff_free(aff); |
1435 | |
1436 | return aff; |
1437 | } |
1438 | |
1439 | /* Look for any divs in the aff->ls with a denominator equal to one |
1440 | * and plug them into the affine expression and any subsequent divs |
1441 | * that may reference the div. |
1442 | */ |
1443 | static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff) |
1444 | { |
1445 | int i; |
1446 | isl_size n; |
1447 | int len; |
1448 | isl_int v; |
1449 | isl_vec *vec; |
1450 | isl_local_space *ls; |
1451 | isl_size off; |
1452 | |
1453 | n = isl_aff_domain_dim(aff, isl_dim_div); |
1454 | off = isl_aff_domain_offset(aff, isl_dim_div); |
1455 | if (n < 0 || off < 0) |
1456 | return isl_aff_free(aff); |
1457 | len = aff->v->size; |
1458 | for (i = 0; i < n; ++i) { |
1459 | if (!isl_int_is_one(aff->ls->div->row[i][0])(isl_sioimath_cmp_si(*(aff->ls->div->row[i][0]), 1) == 0)) |
1460 | continue; |
1461 | ls = isl_local_space_copy(aff->ls); |
1462 | ls = isl_local_space_substitute_seq(ls, isl_dim_div, i, |
1463 | aff->ls->div->row[i], len, i + 1, n - (i + 1)); |
1464 | vec = isl_vec_copy(aff->v); |
1465 | vec = isl_vec_cow(vec); |
1466 | if (!ls || !vec) |
1467 | goto error; |
1468 | |
1469 | isl_int_init(v)isl_sioimath_init((v)); |
1470 | |
1471 | isl_seq_substitute(vec->el, off + i, aff->ls->div->row[i], |
1472 | len, len, v); |
1473 | |
1474 | isl_int_clear(v)isl_sioimath_clear((v)); |
1475 | |
1476 | isl_vec_free(aff->v); |
1477 | aff->v = vec; |
1478 | isl_local_space_free(aff->ls); |
1479 | aff->ls = ls; |
1480 | } |
1481 | |
1482 | return aff; |
1483 | error: |
1484 | isl_vec_free(vec); |
1485 | isl_local_space_free(ls); |
1486 | return isl_aff_free(aff); |
1487 | } |
1488 | |
1489 | /* Look for any divs j that appear with a unit coefficient inside |
1490 | * the definitions of other divs i and plug them into the definitions |
1491 | * of the divs i. |
1492 | * |
1493 | * In particular, an expression of the form |
1494 | * |
1495 | * floor((f(..) + floor(g(..)/n))/m) |
1496 | * |
1497 | * is simplified to |
1498 | * |
1499 | * floor((n * f(..) + g(..))/(n * m)) |
1500 | * |
1501 | * This simplification is correct because we can move the expression |
1502 | * f(..) into the inner floor in the original expression to obtain |
1503 | * |
1504 | * floor(floor((n * f(..) + g(..))/n)/m) |
1505 | * |
1506 | * from which we can derive the simplified expression. |
1507 | */ |
1508 | static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff) |
1509 | { |
1510 | int i, j; |
1511 | isl_size n; |
1512 | isl_size off; |
1513 | |
1514 | n = isl_aff_domain_dim(aff, isl_dim_div); |
1515 | off = isl_aff_domain_offset(aff, isl_dim_div); |
1516 | if (n < 0 || off < 0) |
1517 | return isl_aff_free(aff); |
1518 | for (i = 1; i < n; ++i) { |
1519 | for (j = 0; j < i; ++j) { |
1520 | if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j])(isl_sioimath_cmp_si(*(aff->ls->div->row[i][1 + off + j]), 1) == 0)) |
1521 | continue; |
1522 | aff->ls = isl_local_space_substitute_seq(aff->ls, |
1523 | isl_dim_div, j, aff->ls->div->row[j], |
1524 | aff->v->size, i, 1); |
1525 | if (!aff->ls) |
1526 | return isl_aff_free(aff); |
1527 | } |
1528 | } |
1529 | |
1530 | return aff; |
1531 | } |
1532 | |
1533 | /* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL. |
1534 | * |
1535 | * Even though this function is only called on isl_affs with a single |
1536 | * reference, we are careful to only change aff->v and aff->ls together. |
1537 | */ |
1538 | static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b) |
1539 | { |
1540 | isl_size off = isl_aff_domain_offset(aff, isl_dim_div); |
1541 | isl_local_space *ls; |
1542 | isl_vec *v; |
1543 | |
1544 | if (off < 0) |
1545 | return isl_aff_free(aff); |
1546 | |
1547 | ls = isl_local_space_copy(aff->ls); |
1548 | ls = isl_local_space_swap_div(ls, a, b); |
1549 | v = isl_vec_copy(aff->v); |
1550 | v = isl_vec_cow(v); |
1551 | if (!ls || !v) |
1552 | goto error; |
1553 | |
1554 | isl_int_swap(v->el[1 + off + a], v->el[1 + off + b])isl_sioimath_swap((v->el[1 + off + a]), (v->el[1 + off + b])); |
1555 | isl_vec_free(aff->v); |
1556 | aff->v = v; |
1557 | isl_local_space_free(aff->ls); |
1558 | aff->ls = ls; |
1559 | |
1560 | return aff; |
1561 | error: |
1562 | isl_vec_free(v); |
1563 | isl_local_space_free(ls); |
1564 | return isl_aff_free(aff); |
1565 | } |
1566 | |
1567 | /* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL. |
1568 | * |
1569 | * We currently do not actually remove div "b", but simply add its |
1570 | * coefficient to that of "a" and then zero it out. |
1571 | */ |
1572 | static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b) |
1573 | { |
1574 | isl_size off = isl_aff_domain_offset(aff, isl_dim_div); |
1575 | |
1576 | if (off < 0) |
1577 | return isl_aff_free(aff); |
1578 | |
1579 | if (isl_int_is_zero(aff->v->el[1 + off + b])(isl_sioimath_sgn(*(aff->v->el[1 + off + b])) == 0)) |
1580 | return aff; |
1581 | |
1582 | aff->v = isl_vec_cow(aff->v); |
1583 | if (!aff->v) |
1584 | return isl_aff_free(aff); |
1585 | |
1586 | isl_int_add(aff->v->el[1 + off + a],isl_sioimath_add((aff->v->el[1 + off + a]), *(aff->v ->el[1 + off + a]), *(aff->v->el[1 + off + b])) |
1587 | aff->v->el[1 + off + a], aff->v->el[1 + off + b])isl_sioimath_add((aff->v->el[1 + off + a]), *(aff->v ->el[1 + off + a]), *(aff->v->el[1 + off + b])); |
1588 | isl_int_set_si(aff->v->el[1 + off + b], 0)isl_sioimath_set_si((aff->v->el[1 + off + b]), 0); |
1589 | |
1590 | return aff; |
1591 | } |
1592 | |
1593 | /* Sort the divs in the local space of "aff" according to |
1594 | * the comparison function "cmp_row" in isl_local_space.c, |
1595 | * combining the coefficients of identical divs. |
1596 | * |
1597 | * Reordering divs does not change the semantics of "aff", |
1598 | * so there is no need to call isl_aff_cow. |
1599 | * Moreover, this function is currently only called on isl_affs |
1600 | * with a single reference. |
1601 | */ |
1602 | static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff) |
1603 | { |
1604 | isl_size n; |
1605 | int i, j; |
1606 | |
1607 | n = isl_aff_dim(aff, isl_dim_div); |
1608 | if (n < 0) |
1609 | return isl_aff_free(aff); |
1610 | for (i = 1; i < n; ++i) { |
1611 | for (j = i - 1; j >= 0; --j) { |
1612 | int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1); |
1613 | if (cmp < 0) |
1614 | break; |
1615 | if (cmp == 0) |
1616 | aff = merge_divs(aff, j, j + 1); |
1617 | else |
1618 | aff = swap_div(aff, j, j + 1); |
1619 | if (!aff) |
1620 | return NULL((void*)0); |
1621 | } |
1622 | } |
1623 | |
1624 | return aff; |
1625 | } |
1626 | |
1627 | /* Normalize the representation of "aff". |
1628 | * |
1629 | * This function should only be called on "new" isl_affs, i.e., |
1630 | * with only a single reference. We therefore do not need to |
1631 | * worry about affecting other instances. |
1632 | */ |
1633 | __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff) |
1634 | { |
1635 | if (!aff) |
1636 | return NULL((void*)0); |
1637 | aff->v = isl_vec_normalize(aff->v); |
1638 | if (!aff->v) |
1639 | return isl_aff_free(aff); |
1640 | aff = plug_in_integral_divs(aff); |
1641 | aff = plug_in_unit_divs(aff); |
1642 | aff = sort_divs(aff); |
1643 | aff = isl_aff_remove_unused_divs(aff); |
1644 | return aff; |
1645 | } |
1646 | |
1647 | /* Given f, return floor(f). |
1648 | * If f is an integer expression, then just return f. |
1649 | * If f is a constant, then return the constant floor(f). |
1650 | * Otherwise, if f = g/m, write g = q m + r, |
1651 | * create a new div d = [r/m] and return the expression q + d. |
1652 | * The coefficients in r are taken to lie between -m/2 and m/2. |
1653 | * |
1654 | * reduce_div_coefficients performs the same normalization. |
1655 | * |
1656 | * As a special case, floor(NaN) = NaN. |
1657 | */ |
1658 | __isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff) |
1659 | { |
1660 | int i; |
1661 | int size; |
1662 | isl_ctx *ctx; |
1663 | isl_vec *div; |
1664 | |
1665 | if (!aff) |
1666 | return NULL((void*)0); |
1667 | |
1668 | if (isl_aff_is_nan(aff)) |
1669 | return aff; |
1670 | if (isl_int_is_one(aff->v->el[0])(isl_sioimath_cmp_si(*(aff->v->el[0]), 1) == 0)) |
1671 | return aff; |
1672 | |
1673 | aff = isl_aff_cow(aff); |
1674 | if (!aff) |
1675 | return NULL((void*)0); |
1676 | |
1677 | aff->v = isl_vec_cow(aff->v); |
1678 | if (!aff->v) |
1679 | return isl_aff_free(aff); |
1680 | |
1681 | if (isl_aff_is_cst(aff)) { |
1682 | isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0])isl_sioimath_fdiv_q((aff->v->el[1]), *(aff->v->el [1]), *(aff->v->el[0])); |
1683 | isl_int_set_si(aff->v->el[0], 1)isl_sioimath_set_si((aff->v->el[0]), 1); |
1684 | return aff; |
1685 | } |
1686 | |
1687 | div = isl_vec_copy(aff->v); |
1688 | div = isl_vec_cow(div); |
1689 | if (!div) |
1690 | return isl_aff_free(aff); |
1691 | |
1692 | ctx = isl_aff_get_ctx(aff); |
1693 | isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two)isl_sioimath_fdiv_q((aff->v->el[0]), *(aff->v->el [0]), *(ctx->two)); |
1694 | for (i = 1; i < aff->v->size; ++i) { |
1695 | isl_int_fdiv_r(div->el[i], div->el[i], div->el[0])isl_sioimath_fdiv_r((div->el[i]), *(div->el[i]), *(div-> el[0])); |
1696 | isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0])isl_sioimath_fdiv_q((aff->v->el[i]), *(aff->v->el [i]), *(div->el[0])); |
1697 | if (isl_int_gt(div->el[i], aff->v->el[0])(isl_sioimath_cmp(*(div->el[i]), *(aff->v->el[0])) > 0)) { |
1698 | isl_int_sub(div->el[i], div->el[i], div->el[0])isl_sioimath_sub((div->el[i]), *(div->el[i]), *(div-> el[0])); |
1699 | isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1)isl_sioimath_add_ui((aff->v->el[i]), *(aff->v->el [i]), 1); |
1700 | } |
1701 | } |
1702 | |
1703 | aff->ls = isl_local_space_add_div(aff->ls, div); |
1704 | if (!aff->ls) |
1705 | return isl_aff_free(aff); |
1706 | |
1707 | size = aff->v->size; |
1708 | aff->v = isl_vec_extend(aff->v, size + 1); |
1709 | if (!aff->v) |
1710 | return isl_aff_free(aff); |
1711 | isl_int_set_si(aff->v->el[0], 1)isl_sioimath_set_si((aff->v->el[0]), 1); |
1712 | isl_int_set_si(aff->v->el[size], 1)isl_sioimath_set_si((aff->v->el[size]), 1); |
1713 | |
1714 | aff = isl_aff_normalize(aff); |
1715 | |
1716 | return aff; |
1717 | } |
1718 | |
1719 | /* Compute |
1720 | * |
1721 | * aff mod m = aff - m * floor(aff/m) |
1722 | * |
1723 | * with m an integer value. |
1724 | */ |
1725 | __isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff, |
1726 | __isl_take isl_val *m) |
1727 | { |
1728 | isl_aff *res; |
1729 | |
1730 | if (!aff || !m) |
1731 | goto error; |
1732 | |
1733 | if (!isl_val_is_int(m)) |
1734 | isl_die(isl_val_get_ctx(m), isl_error_invalid,do { isl_handle_error(isl_val_get_ctx(m), isl_error_invalid, "expecting integer modulo" , "polly/lib/External/isl/isl_aff.c", 1735); goto error; } while (0) |
1735 | "expecting integer modulo", goto error)do { isl_handle_error(isl_val_get_ctx(m), isl_error_invalid, "expecting integer modulo" , "polly/lib/External/isl/isl_aff.c", 1735); goto error; } while (0); |
1736 | |
1737 | res = isl_aff_copy(aff); |
1738 | aff = isl_aff_scale_down_val(aff, isl_val_copy(m)); |
1739 | aff = isl_aff_floor(aff); |
1740 | aff = isl_aff_scale_val(aff, m); |
1741 | res = isl_aff_sub(res, aff); |
1742 | |
1743 | return res; |
1744 | error: |
1745 | isl_aff_free(aff); |
1746 | isl_val_free(m); |
1747 | return NULL((void*)0); |
1748 | } |
1749 | |
1750 | /* Compute |
1751 | * |
1752 | * pwaff mod m = pwaff - m * floor(pwaff/m) |
1753 | */ |
1754 | __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m) |
1755 | { |
1756 | isl_pw_aff *res; |
1757 | |
1758 | res = isl_pw_aff_copy(pwaff); |
1759 | pwaff = isl_pw_aff_scale_down(pwaff, m); |
1760 | pwaff = isl_pw_aff_floor(pwaff); |
1761 | pwaff = isl_pw_aff_scale(pwaff, m); |
1762 | res = isl_pw_aff_sub(res, pwaff); |
1763 | |
1764 | return res; |
1765 | } |
1766 | |
1767 | /* Compute |
1768 | * |
1769 | * pa mod m = pa - m * floor(pa/m) |
1770 | * |
1771 | * with m an integer value. |
1772 | */ |
1773 | __isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa, |
1774 | __isl_take isl_val *m) |
1775 | { |
1776 | if (!pa || !m) |
1777 | goto error; |
1778 | if (!isl_val_is_int(m)) |
1779 | isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,do { isl_handle_error(isl_pw_aff_get_ctx(pa), isl_error_invalid , "expecting integer modulo", "polly/lib/External/isl/isl_aff.c" , 1780); goto error; } while (0) |
1780 | "expecting integer modulo", goto error)do { isl_handle_error(isl_pw_aff_get_ctx(pa), isl_error_invalid , "expecting integer modulo", "polly/lib/External/isl/isl_aff.c" , 1780); goto error; } while (0); |
1781 | pa = isl_pw_aff_mod(pa, m->n); |
1782 | isl_val_free(m); |
1783 | return pa; |
1784 | error: |
1785 | isl_pw_aff_free(pa); |
1786 | isl_val_free(m); |
1787 | return NULL((void*)0); |
1788 | } |
1789 | |
1790 | /* Given f, return ceil(f). |
1791 | * If f is an integer expression, then just return f. |
1792 | * Otherwise, let f be the expression |
1793 | * |
1794 | * e/m |
1795 | * |
1796 | * then return |
1797 | * |
1798 | * floor((e + m - 1)/m) |
1799 | * |
1800 | * As a special case, ceil(NaN) = NaN. |
1801 | */ |
1802 | __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff) |
1803 | { |
1804 | if (!aff) |
1805 | return NULL((void*)0); |
1806 | |
1807 | if (isl_aff_is_nan(aff)) |
1808 | return aff; |
1809 | if (isl_int_is_one(aff->v->el[0])(isl_sioimath_cmp_si(*(aff->v->el[0]), 1) == 0)) |
1810 | return aff; |
1811 | |
1812 | aff = isl_aff_cow(aff); |
1813 | if (!aff) |
1814 | return NULL((void*)0); |
1815 | aff->v = isl_vec_cow(aff->v); |
1816 | if (!aff->v) |
1817 | return isl_aff_free(aff); |
1818 | |
1819 | isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0])isl_sioimath_add((aff->v->el[1]), *(aff->v->el[1] ), *(aff->v->el[0])); |
1820 | isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1)isl_sioimath_sub_ui((aff->v->el[1]), *(aff->v->el [1]), 1); |
1821 | aff = isl_aff_floor(aff); |
1822 | |
1823 | return aff; |
1824 | } |
1825 | |
1826 | /* Apply the expansion computed by isl_merge_divs. |
1827 | * The expansion itself is given by "exp" while the resulting |
1828 | * list of divs is given by "div". |
1829 | */ |
1830 | __isl_give isl_aff *isl_aff_expand_divs(__isl_take isl_aff *aff, |
1831 | __isl_take isl_mat *div, int *exp) |
1832 | { |
1833 | isl_size old_n_div; |
1834 | isl_size new_n_div; |
1835 | isl_size offset; |
1836 | |
1837 | aff = isl_aff_cow(aff); |
1838 | |
1839 | offset = isl_aff_domain_offset(aff, isl_dim_div); |
1840 | old_n_div = isl_aff_domain_dim(aff, isl_dim_div); |
1841 | new_n_div = isl_mat_rows(div); |
1842 | if (offset < 0 || old_n_div < 0 || new_n_div < 0) |
1843 | goto error; |
1844 | |
1845 | aff->v = isl_vec_expand(aff->v, 1 + offset, old_n_div, exp, new_n_div); |
1846 | aff->ls = isl_local_space_replace_divs(aff->ls, div); |
1847 | if (!aff->v || !aff->ls) |
1848 | return isl_aff_free(aff); |
1849 | return aff; |
1850 | error: |
1851 | isl_aff_free(aff); |
1852 | isl_mat_free(div); |
1853 | return NULL((void*)0); |
1854 | } |
1855 | |
1856 | /* Add two affine expressions that live in the same local space. |
1857 | */ |
1858 | static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1, |
1859 | __isl_take isl_aff *aff2) |
1860 | { |
1861 | isl_int gcd, f; |
1862 | |
1863 | aff1 = isl_aff_cow(aff1); |
1864 | if (!aff1 || !aff2) |
1865 | goto error; |
1866 | |
1867 | aff1->v = isl_vec_cow(aff1->v); |
1868 | if (!aff1->v) |
1869 | goto error; |
1870 | |
1871 | isl_int_init(gcd)isl_sioimath_init((gcd)); |
1872 | isl_int_init(f)isl_sioimath_init((f)); |
1873 | isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0])isl_sioimath_gcd((gcd), *(aff1->v->el[0]), *(aff2->v ->el[0])); |
1874 | isl_int_divexact(f, aff2->v->el[0], gcd)isl_sioimath_tdiv_q((f), *(aff2->v->el[0]), *(gcd)); |
1875 | isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1); |
1876 | isl_int_divexact(f, aff1->v->el[0], gcd)isl_sioimath_tdiv_q((f), *(aff1->v->el[0]), *(gcd)); |
1877 | isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1); |
1878 | isl_int_divexact(f, aff2->v->el[0], gcd)isl_sioimath_tdiv_q((f), *(aff2->v->el[0]), *(gcd)); |
1879 | isl_int_mul(aff1->v->el[0], aff1->v->el[0], f)isl_sioimath_mul((aff1->v->el[0]), *(aff1->v->el[ 0]), *(f)); |
1880 | isl_int_clear(f)isl_sioimath_clear((f)); |
1881 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); |
1882 | |
1883 | isl_aff_free(aff2); |
1884 | aff1 = isl_aff_normalize(aff1); |
1885 | return aff1; |
1886 | error: |
1887 | isl_aff_free(aff1); |
1888 | isl_aff_free(aff2); |
1889 | return NULL((void*)0); |
1890 | } |
1891 | |
1892 | /* Replace one of the arguments by a NaN and free the other one. |
1893 | */ |
1894 | static __isl_give isl_aff *set_nan_free(__isl_take isl_aff *aff1, |
1895 | __isl_take isl_aff *aff2) |
1896 | { |
1897 | isl_aff_free(aff2); |
1898 | return isl_aff_set_nan(aff1); |
1899 | } |
1900 | |
1901 | /* Return the sum of "aff1" and "aff2". |
1902 | * |
1903 | * If either of the two is NaN, then the result is NaN. |
1904 | */ |
1905 | __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1, |
1906 | __isl_take isl_aff *aff2) |
1907 | { |
1908 | isl_ctx *ctx; |
1909 | int *exp1 = NULL((void*)0); |
1910 | int *exp2 = NULL((void*)0); |
1911 | isl_mat *div; |
1912 | isl_size n_div1, n_div2; |
1913 | |
1914 | if (!aff1 || !aff2) |
1915 | goto error; |
1916 | |
1917 | ctx = isl_aff_get_ctx(aff1); |
1918 | if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim)) |
1919 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 1920); goto error; } while (0) |
1920 | "spaces don't match", goto error)do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 1920); goto error; } while (0); |
1921 | |
1922 | if (isl_aff_is_nan(aff1)) { |
1923 | isl_aff_free(aff2); |
1924 | return aff1; |
1925 | } |
1926 | if (isl_aff_is_nan(aff2)) { |
1927 | isl_aff_free(aff1); |
1928 | return aff2; |
1929 | } |
1930 | |
1931 | n_div1 = isl_aff_dim(aff1, isl_dim_div); |
1932 | n_div2 = isl_aff_dim(aff2, isl_dim_div); |
1933 | if (n_div1 < 0 || n_div2 < 0) |
1934 | goto error; |
1935 | if (n_div1 == 0 && n_div2 == 0) |
1936 | return add_expanded(aff1, aff2); |
1937 | |
1938 | exp1 = isl_alloc_array(ctx, int, n_div1)((int *)isl_malloc_or_die(ctx, (n_div1)*sizeof(int))); |
1939 | exp2 = isl_alloc_array(ctx, int, n_div2)((int *)isl_malloc_or_die(ctx, (n_div2)*sizeof(int))); |
1940 | if ((n_div1 && !exp1) || (n_div2 && !exp2)) |
1941 | goto error; |
1942 | |
1943 | div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2); |
1944 | aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1); |
1945 | aff2 = isl_aff_expand_divs(aff2, div, exp2); |
1946 | free(exp1); |
1947 | free(exp2); |
1948 | |
1949 | return add_expanded(aff1, aff2); |
1950 | error: |
1951 | free(exp1); |
1952 | free(exp2); |
1953 | isl_aff_free(aff1); |
1954 | isl_aff_free(aff2); |
1955 | return NULL((void*)0); |
1956 | } |
1957 | |
1958 | __isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1, |
1959 | __isl_take isl_aff *aff2) |
1960 | { |
1961 | return isl_aff_add(aff1, isl_aff_neg(aff2)); |
1962 | } |
1963 | |
1964 | /* Return the result of scaling "aff" by a factor of "f". |
1965 | * |
1966 | * As a special case, f * NaN = NaN. |
1967 | */ |
1968 | __isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f) |
1969 | { |
1970 | isl_int gcd; |
1971 | |
1972 | if (!aff) |
1973 | return NULL((void*)0); |
1974 | if (isl_aff_is_nan(aff)) |
1975 | return aff; |
1976 | |
1977 | if (isl_int_is_one(f)(isl_sioimath_cmp_si(*(f), 1) == 0)) |
1978 | return aff; |
1979 | |
1980 | aff = isl_aff_cow(aff); |
1981 | if (!aff) |
1982 | return NULL((void*)0); |
1983 | aff->v = isl_vec_cow(aff->v); |
1984 | if (!aff->v) |
1985 | return isl_aff_free(aff); |
1986 | |
1987 | if (isl_int_is_pos(f)(isl_sioimath_sgn(*(f)) > 0) && isl_int_is_divisible_by(aff->v->el[0], f)isl_sioimath_is_divisible_by(*(aff->v->el[0]), *(f))) { |
1988 | isl_int_divexact(aff->v->el[0], aff->v->el[0], f)isl_sioimath_tdiv_q((aff->v->el[0]), *(aff->v->el [0]), *(f)); |
1989 | return aff; |
1990 | } |
1991 | |
1992 | isl_int_init(gcd)isl_sioimath_init((gcd)); |
1993 | isl_int_gcd(gcd, aff->v->el[0], f)isl_sioimath_gcd((gcd), *(aff->v->el[0]), *(f)); |
1994 | isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd)isl_sioimath_tdiv_q((aff->v->el[0]), *(aff->v->el [0]), *(gcd)); |
1995 | isl_int_divexact(gcd, f, gcd)isl_sioimath_tdiv_q((gcd), *(f), *(gcd)); |
1996 | isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1); |
1997 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); |
1998 | |
1999 | return aff; |
2000 | } |
2001 | |
2002 | /* Multiple "aff" by "v". |
2003 | */ |
2004 | __isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff, |
2005 | __isl_take isl_val *v) |
2006 | { |
2007 | if (!aff || !v) |
2008 | goto error; |
2009 | |
2010 | if (isl_val_is_one(v)) { |
2011 | isl_val_free(v); |
2012 | return aff; |
2013 | } |
2014 | |
2015 | if (!isl_val_is_rat(v)) |
2016 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational factor", "polly/lib/External/isl/isl_aff.c" , 2017); goto error; } while (0) |
2017 | "expecting rational factor", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational factor", "polly/lib/External/isl/isl_aff.c" , 2017); goto error; } while (0); |
2018 | |
2019 | aff = isl_aff_scale(aff, v->n); |
2020 | aff = isl_aff_scale_down(aff, v->d); |
2021 | |
2022 | isl_val_free(v); |
2023 | return aff; |
2024 | error: |
2025 | isl_aff_free(aff); |
2026 | isl_val_free(v); |
2027 | return NULL((void*)0); |
2028 | } |
2029 | |
2030 | /* Return the result of scaling "aff" down by a factor of "f". |
2031 | * |
2032 | * As a special case, NaN/f = NaN. |
2033 | */ |
2034 | __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f) |
2035 | { |
2036 | isl_int gcd; |
2037 | |
2038 | if (!aff) |
2039 | return NULL((void*)0); |
2040 | if (isl_aff_is_nan(aff)) |
2041 | return aff; |
2042 | |
2043 | if (isl_int_is_one(f)(isl_sioimath_cmp_si(*(f), 1) == 0)) |
2044 | return aff; |
2045 | |
2046 | aff = isl_aff_cow(aff); |
2047 | if (!aff) |
2048 | return NULL((void*)0); |
2049 | |
2050 | if (isl_int_is_zero(f)(isl_sioimath_sgn(*(f)) == 0)) |
2051 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot scale down by zero", "polly/lib/External/isl/isl_aff.c" , 2052); return isl_aff_free(aff); } while (0) |
2052 | "cannot scale down by zero", return isl_aff_free(aff))do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot scale down by zero", "polly/lib/External/isl/isl_aff.c" , 2052); return isl_aff_free(aff); } while (0); |
2053 | |
2054 | aff->v = isl_vec_cow(aff->v); |
2055 | if (!aff->v) |
2056 | return isl_aff_free(aff); |
2057 | |
2058 | isl_int_init(gcd)isl_sioimath_init((gcd)); |
2059 | isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd); |
2060 | isl_int_gcd(gcd, gcd, f)isl_sioimath_gcd((gcd), *(gcd), *(f)); |
2061 | isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1); |
2062 | isl_int_divexact(gcd, f, gcd)isl_sioimath_tdiv_q((gcd), *(f), *(gcd)); |
2063 | isl_int_mul(aff->v->el[0], aff->v->el[0], gcd)isl_sioimath_mul((aff->v->el[0]), *(aff->v->el[0] ), *(gcd)); |
2064 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); |
2065 | |
2066 | return aff; |
2067 | } |
2068 | |
2069 | /* Divide "aff" by "v". |
2070 | */ |
2071 | __isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff, |
2072 | __isl_take isl_val *v) |
2073 | { |
2074 | if (!aff || !v) |
2075 | goto error; |
2076 | |
2077 | if (isl_val_is_one(v)) { |
2078 | isl_val_free(v); |
2079 | return aff; |
2080 | } |
2081 | |
2082 | if (!isl_val_is_rat(v)) |
2083 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational factor", "polly/lib/External/isl/isl_aff.c" , 2084); goto error; } while (0) |
2084 | "expecting rational factor", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "expecting rational factor", "polly/lib/External/isl/isl_aff.c" , 2084); goto error; } while (0); |
2085 | if (!isl_val_is_pos(v)) |
2086 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "factor needs to be positive", "polly/lib/External/isl/isl_aff.c" , 2087); goto error; } while (0) |
2087 | "factor needs to be positive", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "factor needs to be positive", "polly/lib/External/isl/isl_aff.c" , 2087); goto error; } while (0); |
2088 | |
2089 | aff = isl_aff_scale(aff, v->d); |
2090 | aff = isl_aff_scale_down(aff, v->n); |
2091 | |
2092 | isl_val_free(v); |
2093 | return aff; |
2094 | error: |
2095 | isl_aff_free(aff); |
2096 | isl_val_free(v); |
2097 | return NULL((void*)0); |
2098 | } |
2099 | |
2100 | __isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f) |
2101 | { |
2102 | isl_int v; |
2103 | |
2104 | if (f == 1) |
2105 | return aff; |
2106 | |
2107 | isl_int_init(v)isl_sioimath_init((v)); |
2108 | isl_int_set_ui(v, f)isl_sioimath_set_ui((v), f); |
2109 | aff = isl_aff_scale_down(aff, v); |
2110 | isl_int_clear(v)isl_sioimath_clear((v)); |
2111 | |
2112 | return aff; |
2113 | } |
2114 | |
2115 | __isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff, |
2116 | enum isl_dim_type type, unsigned pos, const char *s) |
2117 | { |
2118 | aff = isl_aff_cow(aff); |
2119 | if (!aff) |
2120 | return NULL((void*)0); |
2121 | if (type == isl_dim_out) |
2122 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2124); return isl_aff_free (aff); } while (0) |
2123 | "cannot set name of output/set dimension",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2124); return isl_aff_free (aff); } while (0) |
2124 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2124); return isl_aff_free (aff); } while (0); |
2125 | if (type == isl_dim_in) |
2126 | type = isl_dim_set; |
2127 | aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s); |
2128 | if (!aff->ls) |
2129 | return isl_aff_free(aff); |
2130 | |
2131 | return aff; |
2132 | } |
2133 | |
2134 | __isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff, |
2135 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
2136 | { |
2137 | aff = isl_aff_cow(aff); |
2138 | if (!aff) |
2139 | goto error; |
2140 | if (type == isl_dim_out) |
2141 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2143); goto error; } while (0) |
2142 | "cannot set name of output/set dimension",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2143); goto error; } while (0) |
2143 | goto error)do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot set name of output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2143); goto error; } while (0); |
2144 | if (type == isl_dim_in) |
2145 | type = isl_dim_set; |
2146 | aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id); |
2147 | if (!aff->ls) |
2148 | return isl_aff_free(aff); |
2149 | |
2150 | return aff; |
2151 | error: |
2152 | isl_id_free(id); |
2153 | isl_aff_free(aff); |
2154 | return NULL((void*)0); |
2155 | } |
2156 | |
2157 | /* Replace the identifier of the input tuple of "aff" by "id". |
2158 | * type is currently required to be equal to isl_dim_in |
2159 | */ |
2160 | __isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff, |
2161 | enum isl_dim_type type, __isl_take isl_id *id) |
2162 | { |
2163 | aff = isl_aff_cow(aff); |
2164 | if (!aff) |
2165 | goto error; |
2166 | if (type != isl_dim_in) |
2167 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot only set id of input tuple" , "polly/lib/External/isl/isl_aff.c", 2168); goto error; } while (0) |
2168 | "cannot only set id of input tuple", goto error)do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot only set id of input tuple" , "polly/lib/External/isl/isl_aff.c", 2168); goto error; } while (0); |
2169 | aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id); |
2170 | if (!aff->ls) |
2171 | return isl_aff_free(aff); |
2172 | |
2173 | return aff; |
2174 | error: |
2175 | isl_id_free(id); |
2176 | isl_aff_free(aff); |
2177 | return NULL((void*)0); |
2178 | } |
2179 | |
2180 | /* Exploit the equalities in "eq" to simplify the affine expression |
2181 | * and the expressions of the integer divisions in the local space. |
2182 | * The integer divisions in this local space are assumed to appear |
2183 | * as regular dimensions in "eq". |
2184 | */ |
2185 | static __isl_give isl_aff *isl_aff_substitute_equalities_lifted( |
2186 | __isl_take isl_aff *aff, __isl_take isl_basic_setisl_basic_map *eq) |
2187 | { |
2188 | int i, j; |
2189 | unsigned o_div; |
2190 | unsigned n_div; |
2191 | |
2192 | if (!eq) |
2193 | goto error; |
2194 | if (eq->n_eq == 0) { |
2195 | isl_basic_set_free(eq); |
2196 | return aff; |
2197 | } |
2198 | |
2199 | aff = isl_aff_cow(aff); |
2200 | if (!aff) |
2201 | goto error; |
2202 | |
2203 | aff->ls = isl_local_space_substitute_equalities(aff->ls, |
2204 | isl_basic_set_copy(eq)); |
2205 | aff->v = isl_vec_cow(aff->v); |
2206 | if (!aff->ls || !aff->v) |
2207 | goto error; |
2208 | |
2209 | o_div = isl_basic_set_offset(eq, isl_dim_div); |
2210 | n_div = eq->n_div; |
2211 | for (i = 0; i < eq->n_eq; ++i) { |
2212 | j = isl_seq_last_non_zero(eq->eq[i], o_div + n_div); |
2213 | if (j < 0 || j == 0 || j >= o_div) |
2214 | continue; |
2215 | |
2216 | isl_seq_elim(aff->v->el + 1, eq->eq[i], j, o_div, |
2217 | &aff->v->el[0]); |
2218 | } |
2219 | |
2220 | isl_basic_set_free(eq); |
2221 | aff = isl_aff_normalize(aff); |
2222 | return aff; |
2223 | error: |
2224 | isl_basic_set_free(eq); |
2225 | isl_aff_free(aff); |
2226 | return NULL((void*)0); |
2227 | } |
2228 | |
2229 | /* Exploit the equalities in "eq" to simplify the affine expression |
2230 | * and the expressions of the integer divisions in the local space. |
2231 | */ |
2232 | __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff, |
2233 | __isl_take isl_basic_setisl_basic_map *eq) |
2234 | { |
2235 | isl_size n_div; |
2236 | |
2237 | n_div = isl_aff_domain_dim(aff, isl_dim_div); |
2238 | if (n_div < 0) |
2239 | goto error; |
2240 | if (n_div > 0) |
2241 | eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div); |
2242 | return isl_aff_substitute_equalities_lifted(aff, eq); |
2243 | error: |
2244 | isl_basic_set_free(eq); |
2245 | isl_aff_free(aff); |
2246 | return NULL((void*)0); |
2247 | } |
2248 | |
2249 | /* Look for equalities among the variables shared by context and aff |
2250 | * and the integer divisions of aff, if any. |
2251 | * The equalities are then used to eliminate coefficients and/or integer |
2252 | * divisions from aff. |
2253 | */ |
2254 | __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff, |
2255 | __isl_take isl_setisl_map *context) |
2256 | { |
2257 | isl_local_space *ls; |
2258 | isl_basic_setisl_basic_map *hull; |
2259 | |
2260 | ls = isl_aff_get_domain_local_space(aff); |
2261 | context = isl_local_space_lift_set(ls, context); |
2262 | |
2263 | hull = isl_set_affine_hull(context); |
2264 | return isl_aff_substitute_equalities_lifted(aff, hull); |
2265 | } |
2266 | |
2267 | __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff, |
2268 | __isl_take isl_setisl_map *context) |
2269 | { |
2270 | isl_setisl_map *dom_context = isl_set_universe(isl_aff_get_domain_space(aff)); |
2271 | dom_context = isl_set_intersect_params(dom_context, context); |
2272 | return isl_aff_gist(aff, dom_context); |
2273 | } |
2274 | |
2275 | /* Return a basic set containing those elements in the space |
2276 | * of aff where it is positive. "rational" should not be set. |
2277 | * |
2278 | * If "aff" is NaN, then it is not positive. |
2279 | */ |
2280 | static __isl_give isl_basic_setisl_basic_map *aff_pos_basic_set(__isl_take isl_aff *aff, |
2281 | int rational, void *user) |
2282 | { |
2283 | isl_constraint *ineq; |
2284 | isl_basic_setisl_basic_map *bset; |
2285 | isl_val *c; |
2286 | |
2287 | if (!aff) |
2288 | return NULL((void*)0); |
2289 | if (isl_aff_is_nan(aff)) { |
2290 | isl_space *space = isl_aff_get_domain_space(aff); |
2291 | isl_aff_free(aff); |
2292 | return isl_basic_set_empty(space); |
2293 | } |
2294 | if (rational) |
2295 | isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "rational sets not supported", "polly/lib/External/isl/isl_aff.c" , 2296); goto error; } while (0) |
2296 | "rational sets not supported", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "rational sets not supported", "polly/lib/External/isl/isl_aff.c" , 2296); goto error; } while (0); |
2297 | |
2298 | ineq = isl_inequality_from_aff(aff); |
2299 | c = isl_constraint_get_constant_val(ineq); |
2300 | c = isl_val_sub_ui(c, 1); |
2301 | ineq = isl_constraint_set_constant_val(ineq, c); |
2302 | |
2303 | bset = isl_basic_set_from_constraint(ineq); |
2304 | bset = isl_basic_set_simplify(bset); |
2305 | return bset; |
2306 | error: |
2307 | isl_aff_free(aff); |
2308 | return NULL((void*)0); |
2309 | } |
2310 | |
2311 | /* Return a basic set containing those elements in the space |
2312 | * of aff where it is non-negative. |
2313 | * If "rational" is set, then return a rational basic set. |
2314 | * |
2315 | * If "aff" is NaN, then it is not non-negative (it's not negative either). |
2316 | */ |
2317 | static __isl_give isl_basic_setisl_basic_map *aff_nonneg_basic_set( |
2318 | __isl_take isl_aff *aff, int rational, void *user) |
2319 | { |
2320 | isl_constraint *ineq; |
2321 | isl_basic_setisl_basic_map *bset; |
2322 | |
2323 | if (!aff) |
2324 | return NULL((void*)0); |
2325 | if (isl_aff_is_nan(aff)) { |
2326 | isl_space *space = isl_aff_get_domain_space(aff); |
2327 | isl_aff_free(aff); |
2328 | return isl_basic_set_empty(space); |
2329 | } |
2330 | |
2331 | ineq = isl_inequality_from_aff(aff); |
2332 | |
2333 | bset = isl_basic_set_from_constraint(ineq); |
2334 | if (rational) |
2335 | bset = isl_basic_set_set_rational(bset); |
2336 | bset = isl_basic_set_simplify(bset); |
2337 | return bset; |
2338 | } |
2339 | |
2340 | /* Return a basic set containing those elements in the space |
2341 | * of aff where it is non-negative. |
2342 | */ |
2343 | __isl_give isl_basic_setisl_basic_map *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff) |
2344 | { |
2345 | return aff_nonneg_basic_set(aff, 0, NULL((void*)0)); |
2346 | } |
2347 | |
2348 | /* Return a basic set containing those elements in the domain space |
2349 | * of "aff" where it is positive. |
2350 | */ |
2351 | __isl_give isl_basic_setisl_basic_map *isl_aff_pos_basic_set(__isl_take isl_aff *aff) |
2352 | { |
2353 | aff = isl_aff_add_constant_num_si(aff, -1); |
2354 | return isl_aff_nonneg_basic_set(aff); |
2355 | } |
2356 | |
2357 | /* Return a basic set containing those elements in the domain space |
2358 | * of aff where it is negative. |
2359 | */ |
2360 | __isl_give isl_basic_setisl_basic_map *isl_aff_neg_basic_set(__isl_take isl_aff *aff) |
2361 | { |
2362 | aff = isl_aff_neg(aff); |
2363 | return isl_aff_pos_basic_set(aff); |
2364 | } |
2365 | |
2366 | /* Return a basic set containing those elements in the space |
2367 | * of aff where it is zero. |
2368 | * If "rational" is set, then return a rational basic set. |
2369 | * |
2370 | * If "aff" is NaN, then it is not zero. |
2371 | */ |
2372 | static __isl_give isl_basic_setisl_basic_map *aff_zero_basic_set(__isl_take isl_aff *aff, |
2373 | int rational, void *user) |
2374 | { |
2375 | isl_constraint *ineq; |
2376 | isl_basic_setisl_basic_map *bset; |
2377 | |
2378 | if (!aff) |
2379 | return NULL((void*)0); |
2380 | if (isl_aff_is_nan(aff)) { |
2381 | isl_space *space = isl_aff_get_domain_space(aff); |
2382 | isl_aff_free(aff); |
2383 | return isl_basic_set_empty(space); |
2384 | } |
2385 | |
2386 | ineq = isl_equality_from_aff(aff); |
2387 | |
2388 | bset = isl_basic_set_from_constraint(ineq); |
2389 | if (rational) |
2390 | bset = isl_basic_set_set_rational(bset); |
2391 | bset = isl_basic_set_simplify(bset); |
2392 | return bset; |
2393 | } |
2394 | |
2395 | /* Return a basic set containing those elements in the space |
2396 | * of aff where it is zero. |
2397 | */ |
2398 | __isl_give isl_basic_setisl_basic_map *isl_aff_zero_basic_set(__isl_take isl_aff *aff) |
2399 | { |
2400 | return aff_zero_basic_set(aff, 0, NULL((void*)0)); |
2401 | } |
2402 | |
2403 | /* Return a basic set containing those elements in the shared space |
2404 | * of aff1 and aff2 where aff1 is greater than or equal to aff2. |
2405 | */ |
2406 | __isl_give isl_basic_setisl_basic_map *isl_aff_ge_basic_set(__isl_take isl_aff *aff1, |
2407 | __isl_take isl_aff *aff2) |
2408 | { |
2409 | aff1 = isl_aff_sub(aff1, aff2); |
2410 | |
2411 | return isl_aff_nonneg_basic_set(aff1); |
2412 | } |
2413 | |
2414 | /* Return a basic set containing those elements in the shared domain space |
2415 | * of "aff1" and "aff2" where "aff1" is greater than "aff2". |
2416 | */ |
2417 | __isl_give isl_basic_setisl_basic_map *isl_aff_gt_basic_set(__isl_take isl_aff *aff1, |
2418 | __isl_take isl_aff *aff2) |
2419 | { |
2420 | aff1 = isl_aff_sub(aff1, aff2); |
2421 | |
2422 | return isl_aff_pos_basic_set(aff1); |
2423 | } |
2424 | |
2425 | /* Return a set containing those elements in the shared space |
2426 | * of aff1 and aff2 where aff1 is greater than or equal to aff2. |
2427 | */ |
2428 | __isl_give isl_setisl_map *isl_aff_ge_set(__isl_take isl_aff *aff1, |
2429 | __isl_take isl_aff *aff2) |
2430 | { |
2431 | return isl_set_from_basic_set(isl_aff_ge_basic_set(aff1, aff2)); |
2432 | } |
2433 | |
2434 | /* Return a set containing those elements in the shared domain space |
2435 | * of aff1 and aff2 where aff1 is greater than aff2. |
2436 | * |
2437 | * If either of the two inputs is NaN, then the result is empty, |
2438 | * as comparisons with NaN always return false. |
2439 | */ |
2440 | __isl_give isl_setisl_map *isl_aff_gt_set(__isl_take isl_aff *aff1, |
2441 | __isl_take isl_aff *aff2) |
2442 | { |
2443 | return isl_set_from_basic_set(isl_aff_gt_basic_set(aff1, aff2)); |
2444 | } |
2445 | |
2446 | /* Return a basic set containing those elements in the shared space |
2447 | * of aff1 and aff2 where aff1 is smaller than or equal to aff2. |
2448 | */ |
2449 | __isl_give isl_basic_setisl_basic_map *isl_aff_le_basic_set(__isl_take isl_aff *aff1, |
2450 | __isl_take isl_aff *aff2) |
2451 | { |
2452 | return isl_aff_ge_basic_set(aff2, aff1); |
2453 | } |
2454 | |
2455 | /* Return a basic set containing those elements in the shared domain space |
2456 | * of "aff1" and "aff2" where "aff1" is smaller than "aff2". |
2457 | */ |
2458 | __isl_give isl_basic_setisl_basic_map *isl_aff_lt_basic_set(__isl_take isl_aff *aff1, |
2459 | __isl_take isl_aff *aff2) |
2460 | { |
2461 | return isl_aff_gt_basic_set(aff2, aff1); |
2462 | } |
2463 | |
2464 | /* Return a set containing those elements in the shared space |
2465 | * of aff1 and aff2 where aff1 is smaller than or equal to aff2. |
2466 | */ |
2467 | __isl_give isl_setisl_map *isl_aff_le_set(__isl_take isl_aff *aff1, |
2468 | __isl_take isl_aff *aff2) |
2469 | { |
2470 | return isl_aff_ge_set(aff2, aff1); |
2471 | } |
2472 | |
2473 | /* Return a set containing those elements in the shared domain space |
2474 | * of "aff1" and "aff2" where "aff1" is smaller than "aff2". |
2475 | */ |
2476 | __isl_give isl_setisl_map *isl_aff_lt_set(__isl_take isl_aff *aff1, |
2477 | __isl_take isl_aff *aff2) |
2478 | { |
2479 | return isl_set_from_basic_set(isl_aff_lt_basic_set(aff1, aff2)); |
2480 | } |
2481 | |
2482 | /* Return a basic set containing those elements in the shared space |
2483 | * of aff1 and aff2 where aff1 and aff2 are equal. |
2484 | */ |
2485 | __isl_give isl_basic_setisl_basic_map *isl_aff_eq_basic_set(__isl_take isl_aff *aff1, |
2486 | __isl_take isl_aff *aff2) |
2487 | { |
2488 | aff1 = isl_aff_sub(aff1, aff2); |
2489 | |
2490 | return isl_aff_zero_basic_set(aff1); |
2491 | } |
2492 | |
2493 | /* Return a set containing those elements in the shared space |
2494 | * of aff1 and aff2 where aff1 and aff2 are equal. |
2495 | */ |
2496 | __isl_give isl_setisl_map *isl_aff_eq_set(__isl_take isl_aff *aff1, |
2497 | __isl_take isl_aff *aff2) |
2498 | { |
2499 | return isl_set_from_basic_set(isl_aff_eq_basic_set(aff1, aff2)); |
2500 | } |
2501 | |
2502 | /* Return a set containing those elements in the shared domain space |
2503 | * of aff1 and aff2 where aff1 and aff2 are not equal. |
2504 | * |
2505 | * If either of the two inputs is NaN, then the result is empty, |
2506 | * as comparisons with NaN always return false. |
2507 | */ |
2508 | __isl_give isl_setisl_map *isl_aff_ne_set(__isl_take isl_aff *aff1, |
2509 | __isl_take isl_aff *aff2) |
2510 | { |
2511 | isl_setisl_map *set_lt, *set_gt; |
2512 | |
2513 | set_lt = isl_aff_lt_set(isl_aff_copy(aff1), |
2514 | isl_aff_copy(aff2)); |
2515 | set_gt = isl_aff_gt_set(aff1, aff2); |
2516 | return isl_set_union_disjoint(set_lt, set_gt); |
2517 | } |
2518 | |
2519 | __isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_setisl_map *dom, |
2520 | __isl_take isl_aff *aff1, __isl_take isl_aff *aff2) |
2521 | { |
2522 | aff1 = isl_aff_add(aff1, aff2); |
2523 | aff1 = isl_aff_gist(aff1, isl_set_copy(dom)); |
2524 | return aff1; |
2525 | } |
2526 | |
2527 | isl_bool isl_aff_is_empty(__isl_keep isl_aff *aff) |
2528 | { |
2529 | if (!aff) |
2530 | return isl_bool_error; |
2531 | |
2532 | return isl_bool_false; |
2533 | } |
2534 | |
2535 | #undef TYPEisl_multi_union_pw_aff |
2536 | #define TYPEisl_multi_union_pw_aff isl_aff |
2537 | static |
2538 | #include "check_type_range_templ.c" |
2539 | |
2540 | /* Check whether the given affine expression has non-zero coefficient |
2541 | * for any dimension in the given range or if any of these dimensions |
2542 | * appear with non-zero coefficients in any of the integer divisions |
2543 | * involved in the affine expression. |
2544 | */ |
2545 | isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff, |
2546 | enum isl_dim_type type, unsigned first, unsigned n) |
2547 | { |
2548 | int i; |
2549 | int *active = NULL((void*)0); |
2550 | isl_bool involves = isl_bool_false; |
2551 | |
2552 | if (!aff) |
2553 | return isl_bool_error; |
2554 | if (n == 0) |
2555 | return isl_bool_false; |
2556 | if (isl_aff_check_range(aff, type, first, n) < 0) |
2557 | return isl_bool_error; |
2558 | |
2559 | active = isl_local_space_get_active(aff->ls, aff->v->el + 2); |
2560 | if (!active) |
2561 | goto error; |
2562 | |
2563 | first += isl_local_space_offset(aff->ls, type) - 1; |
2564 | for (i = 0; i < n; ++i) |
2565 | if (active[first + i]) { |
2566 | involves = isl_bool_true; |
2567 | break; |
2568 | } |
2569 | |
2570 | free(active); |
2571 | |
2572 | return involves; |
2573 | error: |
2574 | free(active); |
2575 | return isl_bool_error; |
2576 | } |
2577 | |
2578 | /* Does "aff" involve any local variables, i.e., integer divisions? |
2579 | */ |
2580 | isl_bool isl_aff_involves_locals(__isl_keep isl_aff *aff) |
2581 | { |
2582 | isl_size n; |
2583 | |
2584 | n = isl_aff_dim(aff, isl_dim_div); |
2585 | if (n < 0) |
2586 | return isl_bool_error; |
2587 | return isl_bool_ok(n > 0); |
2588 | } |
2589 | |
2590 | __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff, |
2591 | enum isl_dim_type type, unsigned first, unsigned n) |
2592 | { |
2593 | isl_ctx *ctx; |
2594 | |
2595 | if (!aff) |
2596 | return NULL((void*)0); |
2597 | if (type == isl_dim_out) |
2598 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot drop output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2600); return isl_aff_free (aff); } while (0) |
2599 | "cannot drop output/set dimension",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot drop output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2600); return isl_aff_free (aff); } while (0) |
2600 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot drop output/set dimension" , "polly/lib/External/isl/isl_aff.c", 2600); return isl_aff_free (aff); } while (0); |
2601 | if (type == isl_dim_in) |
2602 | type = isl_dim_set; |
2603 | if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type)) |
2604 | return aff; |
2605 | |
2606 | ctx = isl_aff_get_ctx(aff); |
Value stored to 'ctx' is never read | |
2607 | if (isl_local_space_check_range(aff->ls, type, first, n) < 0) |
2608 | return isl_aff_free(aff); |
2609 | |
2610 | aff = isl_aff_cow(aff); |
2611 | if (!aff) |
2612 | return NULL((void*)0); |
2613 | |
2614 | aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n); |
2615 | if (!aff->ls) |
2616 | return isl_aff_free(aff); |
2617 | |
2618 | first += 1 + isl_local_space_offset(aff->ls, type); |
2619 | aff->v = isl_vec_drop_els(aff->v, first, n); |
2620 | if (!aff->v) |
2621 | return isl_aff_free(aff); |
2622 | |
2623 | return aff; |
2624 | } |
2625 | |
2626 | /* Is the domain of "aff" a product? |
2627 | */ |
2628 | static isl_bool isl_aff_domain_is_product(__isl_keep isl_aff *aff) |
2629 | { |
2630 | return isl_space_is_product(isl_aff_peek_domain_space(aff)); |
2631 | } |
2632 | |
2633 | #undef TYPEisl_multi_union_pw_aff |
2634 | #define TYPEisl_multi_union_pw_aff isl_aff |
2635 | #include <isl_domain_factor_templ.c> |
2636 | |
2637 | /* Project the domain of the affine expression onto its parameter space. |
2638 | * The affine expression may not involve any of the domain dimensions. |
2639 | */ |
2640 | __isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff) |
2641 | { |
2642 | isl_space *space; |
2643 | isl_size n; |
2644 | |
2645 | n = isl_aff_dim(aff, isl_dim_in); |
2646 | if (n < 0) |
2647 | return isl_aff_free(aff); |
2648 | aff = isl_aff_drop_domain(aff, 0, n); |
2649 | space = isl_aff_get_domain_space(aff); |
2650 | space = isl_space_params(space); |
2651 | aff = isl_aff_reset_domain_space(aff, space); |
2652 | return aff; |
2653 | } |
2654 | |
2655 | /* Convert an affine expression defined over a parameter domain |
2656 | * into one that is defined over a zero-dimensional set. |
2657 | */ |
2658 | __isl_give isl_aff *isl_aff_from_range(__isl_take isl_aff *aff) |
2659 | { |
2660 | isl_local_space *ls; |
2661 | |
2662 | ls = isl_aff_take_domain_local_space(aff); |
2663 | ls = isl_local_space_set_from_params(ls); |
2664 | aff = isl_aff_restore_domain_local_space(aff, ls); |
2665 | |
2666 | return aff; |
2667 | } |
2668 | |
2669 | __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff, |
2670 | enum isl_dim_type type, unsigned first, unsigned n) |
2671 | { |
2672 | isl_ctx *ctx; |
2673 | |
2674 | if (!aff) |
2675 | return NULL((void*)0); |
2676 | if (type == isl_dim_out) |
2677 | isl_die(aff->v->ctx, isl_error_invalid,do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot insert output/set dimensions" , "polly/lib/External/isl/isl_aff.c", 2679); return isl_aff_free (aff); } while (0) |
2678 | "cannot insert output/set dimensions",do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot insert output/set dimensions" , "polly/lib/External/isl/isl_aff.c", 2679); return isl_aff_free (aff); } while (0) |
2679 | return isl_aff_free(aff))do { isl_handle_error(aff->v->ctx, isl_error_invalid, "cannot insert output/set dimensions" , "polly/lib/External/isl/isl_aff.c", 2679); return isl_aff_free (aff); } while (0); |
2680 | if (type == isl_dim_in) |
2681 | type = isl_dim_set; |
2682 | if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type)) |
2683 | return aff; |
2684 | |
2685 | ctx = isl_aff_get_ctx(aff); |
2686 | if (isl_local_space_check_range(aff->ls, type, first, 0) < 0) |
2687 | return isl_aff_free(aff); |
2688 | |
2689 | aff = isl_aff_cow(aff); |
2690 | if (!aff) |
2691 | return NULL((void*)0); |
2692 | |
2693 | aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n); |
2694 | if (!aff->ls) |
2695 | return isl_aff_free(aff); |
2696 | |
2697 | first += 1 + isl_local_space_offset(aff->ls, type); |
2698 | aff->v = isl_vec_insert_zero_els(aff->v, first, n); |
2699 | if (!aff->v) |
2700 | return isl_aff_free(aff); |
2701 | |
2702 | return aff; |
2703 | } |
2704 | |
2705 | __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff, |
2706 | enum isl_dim_type type, unsigned n) |
2707 | { |
2708 | isl_size pos; |
2709 | |
2710 | pos = isl_aff_dim(aff, type); |
2711 | if (pos < 0) |
2712 | return isl_aff_free(aff); |
2713 | |
2714 | return isl_aff_insert_dims(aff, type, pos, n); |
2715 | } |
2716 | |
2717 | /* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff" |
2718 | * to dimensions of "dst_type" at "dst_pos". |
2719 | * |
2720 | * We only support moving input dimensions to parameters and vice versa. |
2721 | */ |
2722 | __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff, |
2723 | enum isl_dim_type dst_type, unsigned dst_pos, |
2724 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
2725 | { |
2726 | unsigned g_dst_pos; |
2727 | unsigned g_src_pos; |
2728 | isl_size src_off, dst_off; |
2729 | |
2730 | if (!aff) |
2731 | return NULL((void*)0); |
2732 | if (n == 0 && |
2733 | !isl_local_space_is_named_or_nested(aff->ls, src_type) && |
2734 | !isl_local_space_is_named_or_nested(aff->ls, dst_type)) |
2735 | return aff; |
2736 | |
2737 | if (dst_type == isl_dim_out || src_type == isl_dim_out) |
2738 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot move output/set dimension", "polly/lib/External/isl/isl_aff.c" , 2740); return isl_aff_free(aff); } while (0) |
2739 | "cannot move output/set dimension",do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot move output/set dimension", "polly/lib/External/isl/isl_aff.c" , 2740); return isl_aff_free(aff); } while (0) |
2740 | return isl_aff_free(aff))do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot move output/set dimension", "polly/lib/External/isl/isl_aff.c" , 2740); return isl_aff_free(aff); } while (0); |
2741 | if (dst_type == isl_dim_div || src_type == isl_dim_div) |
2742 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot move divs", "polly/lib/External/isl/isl_aff.c", 2743 ); return isl_aff_free(aff); } while (0) |
2743 | "cannot move divs", return isl_aff_free(aff))do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "cannot move divs", "polly/lib/External/isl/isl_aff.c", 2743 ); return isl_aff_free(aff); } while (0); |
2744 | if (dst_type == isl_dim_in) |
2745 | dst_type = isl_dim_set; |
2746 | if (src_type == isl_dim_in) |
2747 | src_type = isl_dim_set; |
2748 | |
2749 | if (isl_local_space_check_range(aff->ls, src_type, src_pos, n) < 0) |
2750 | return isl_aff_free(aff); |
2751 | if (dst_type == src_type) |
2752 | isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "moving dims within the same type not supported", "polly/lib/External/isl/isl_aff.c" , 2754); return isl_aff_free(aff); } while (0) |
2753 | "moving dims within the same type not supported",do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "moving dims within the same type not supported", "polly/lib/External/isl/isl_aff.c" , 2754); return isl_aff_free(aff); } while (0) |
2754 | return isl_aff_free(aff))do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "moving dims within the same type not supported", "polly/lib/External/isl/isl_aff.c" , 2754); return isl_aff_free(aff); } while (0); |
2755 | |
2756 | aff = isl_aff_cow(aff); |
2757 | src_off = isl_aff_domain_offset(aff, src_type); |
2758 | dst_off = isl_aff_domain_offset(aff, dst_type); |
2759 | if (src_off < 0 || dst_off < 0) |
2760 | return isl_aff_free(aff); |
2761 | |
2762 | g_src_pos = 1 + src_off + src_pos; |
2763 | g_dst_pos = 1 + dst_off + dst_pos; |
2764 | if (dst_type > src_type) |
2765 | g_dst_pos -= n; |
2766 | |
2767 | aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n); |
2768 | aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos, |
2769 | src_type, src_pos, n); |
2770 | if (!aff->v || !aff->ls) |
2771 | return isl_aff_free(aff); |
2772 | |
2773 | aff = sort_divs(aff); |
2774 | |
2775 | return aff; |
2776 | } |
2777 | |
2778 | /* Return a zero isl_aff in the given space. |
2779 | * |
2780 | * This is a helper function for isl_pw_*_as_* that ensures a uniform |
2781 | * interface over all piecewise types. |
2782 | */ |
2783 | static __isl_give isl_aff *isl_aff_zero_in_space(__isl_take isl_space *space) |
2784 | { |
2785 | isl_local_space *ls; |
2786 | |
2787 | ls = isl_local_space_from_space(isl_space_domain(space)); |
2788 | return isl_aff_zero_on_domain(ls); |
2789 | } |
2790 | |
2791 | #define isl_aff_involves_nanisl_aff_is_nan isl_aff_is_nan |
2792 | |
2793 | #undef PWisl_pw_union_pw_aff |
2794 | #define PWisl_pw_union_pw_aff isl_pw_aff |
2795 | #undef BASEunion_pw_aff |
2796 | #define BASEunion_pw_aff aff |
2797 | #undef EL_IS_ZEROis_empty |
2798 | #define EL_IS_ZEROis_empty is_empty |
2799 | #undef ZEROempty |
2800 | #define ZEROempty empty |
2801 | #undef IS_ZEROis_empty |
2802 | #define IS_ZEROis_empty is_empty |
2803 | #undef FIELDmaff |
2804 | #define FIELDmaff aff |
2805 | #undef DEFAULT_IS_ZERO0 |
2806 | #define DEFAULT_IS_ZERO0 0 |
2807 | |
2808 | #include <isl_pw_templ.c> |
2809 | #include <isl_pw_add_constant_val_templ.c> |
2810 | #include <isl_pw_bind_domain_templ.c> |
2811 | #include <isl_pw_eval.c> |
2812 | #include <isl_pw_hash.c> |
2813 | #include <isl_pw_insert_dims_templ.c> |
2814 | #include <isl_pw_insert_domain_templ.c> |
2815 | #include <isl_pw_move_dims_templ.c> |
2816 | #include <isl_pw_neg_templ.c> |
2817 | #include <isl_pw_pullback_templ.c> |
2818 | #include <isl_pw_sub_templ.c> |
2819 | #include <isl_pw_union_opt.c> |
2820 | |
2821 | #undef BASEunion_pw_aff |
2822 | #define BASEunion_pw_aff pw_aff |
2823 | |
2824 | #include <isl_union_single.c> |
2825 | #include <isl_union_neg.c> |
2826 | |
2827 | #undef BASEunion_pw_aff |
2828 | #define BASEunion_pw_aff aff |
2829 | |
2830 | #include <isl_union_pw_templ.c> |
2831 | |
2832 | /* Compute a piecewise quasi-affine expression with a domain that |
2833 | * is the union of those of pwaff1 and pwaff2 and such that on each |
2834 | * cell, the quasi-affine expression is the maximum of those of pwaff1 |
2835 | * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given |
2836 | * cell, then the associated expression is the defined one. |
2837 | */ |
2838 | __isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1, |
2839 | __isl_take isl_pw_aff *pwaff2) |
2840 | { |
2841 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
2842 | return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_set); |
2843 | } |
2844 | |
2845 | /* Compute a piecewise quasi-affine expression with a domain that |
2846 | * is the union of those of pwaff1 and pwaff2 and such that on each |
2847 | * cell, the quasi-affine expression is the minimum of those of pwaff1 |
2848 | * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given |
2849 | * cell, then the associated expression is the defined one. |
2850 | */ |
2851 | __isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1, |
2852 | __isl_take isl_pw_aff *pwaff2) |
2853 | { |
2854 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
2855 | return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_set); |
2856 | } |
2857 | |
2858 | __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1, |
2859 | __isl_take isl_pw_aff *pwaff2, int max) |
2860 | { |
2861 | if (max) |
2862 | return isl_pw_aff_union_max(pwaff1, pwaff2); |
2863 | else |
2864 | return isl_pw_aff_union_min(pwaff1, pwaff2); |
2865 | } |
2866 | |
2867 | /* Is the domain of "pa" a product? |
2868 | */ |
2869 | static isl_bool isl_pw_aff_domain_is_product(__isl_keep isl_pw_aff *pa) |
2870 | { |
2871 | return isl_space_domain_is_wrapping(isl_pw_aff_peek_space(pa)); |
2872 | } |
2873 | |
2874 | #undef TYPEisl_multi_union_pw_aff |
2875 | #define TYPEisl_multi_union_pw_aff isl_pw_aff |
2876 | #include <isl_domain_factor_templ.c> |
2877 | |
2878 | /* Return a set containing those elements in the domain |
2879 | * of "pwaff" where it satisfies "fn" (if complement is 0) or |
2880 | * does not satisfy "fn" (if complement is 1). |
2881 | * |
2882 | * The pieces with a NaN never belong to the result since |
2883 | * NaN does not satisfy any property. |
2884 | */ |
2885 | static __isl_give isl_setisl_map *pw_aff_locus(__isl_take isl_pw_aff *pwaff, |
2886 | __isl_give isl_basic_setisl_basic_map *(*fn)(__isl_take isl_aff *aff, int rational, |
2887 | void *user), |
2888 | int complement, void *user) |
2889 | { |
2890 | int i; |
2891 | isl_setisl_map *set; |
2892 | |
2893 | if (!pwaff) |
2894 | return NULL((void*)0); |
2895 | |
2896 | set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff)); |
2897 | |
2898 | for (i = 0; i < pwaff->n; ++i) { |
2899 | isl_basic_setisl_basic_map *bset; |
2900 | isl_setisl_map *set_i, *locus; |
2901 | isl_bool rational; |
2902 | |
2903 | if (isl_aff_is_nan(pwaff->p[i].aff)) |
2904 | continue; |
2905 | |
2906 | rational = isl_set_has_rational(pwaff->p[i].set); |
2907 | bset = fn(isl_aff_copy(pwaff->p[i].aff), rational, user); |
2908 | locus = isl_set_from_basic_set(bset); |
2909 | set_i = isl_set_copy(pwaff->p[i].set); |
2910 | if (complement) |
2911 | set_i = isl_set_subtract(set_i, locus); |
2912 | else |
2913 | set_i = isl_set_intersect(set_i, locus); |
2914 | set = isl_set_union_disjoint(set, set_i); |
2915 | } |
2916 | |
2917 | isl_pw_aff_free(pwaff); |
2918 | |
2919 | return set; |
2920 | } |
2921 | |
2922 | /* Return a set containing those elements in the domain |
2923 | * of "pa" where it is positive. |
2924 | */ |
2925 | __isl_give isl_setisl_map *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa) |
2926 | { |
2927 | return pw_aff_locus(pa, &aff_pos_basic_set, 0, NULL((void*)0)); |
2928 | } |
2929 | |
2930 | /* Return a set containing those elements in the domain |
2931 | * of pwaff where it is non-negative. |
2932 | */ |
2933 | __isl_give isl_setisl_map *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff) |
2934 | { |
2935 | return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0, NULL((void*)0)); |
2936 | } |
2937 | |
2938 | /* Return a set containing those elements in the domain |
2939 | * of pwaff where it is zero. |
2940 | */ |
2941 | __isl_give isl_setisl_map *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) |
2942 | { |
2943 | return pw_aff_locus(pwaff, &aff_zero_basic_set, 0, NULL((void*)0)); |
2944 | } |
2945 | |
2946 | /* Return a set containing those elements in the domain |
2947 | * of pwaff where it is not zero. |
2948 | */ |
2949 | __isl_give isl_setisl_map *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff) |
2950 | { |
2951 | return pw_aff_locus(pwaff, &aff_zero_basic_set, 1, NULL((void*)0)); |
2952 | } |
2953 | |
2954 | /* Bind the affine function "aff" to the parameter "id", |
2955 | * returning the elements in the domain where the affine expression |
2956 | * is equal to the parameter. |
2957 | */ |
2958 | __isl_give isl_basic_setisl_basic_map *isl_aff_bind_id(__isl_take isl_aff *aff, |
2959 | __isl_take isl_id *id) |
2960 | { |
2961 | isl_space *space; |
2962 | isl_aff *aff_id; |
2963 | |
2964 | space = isl_aff_get_domain_space(aff); |
2965 | space = isl_space_add_param_id(space, isl_id_copy(id)); |
2966 | |
2967 | aff = isl_aff_align_params(aff, isl_space_copy(space)); |
2968 | aff_id = isl_aff_param_on_domain_space_id(space, id); |
2969 | |
2970 | return isl_aff_eq_basic_set(aff, aff_id); |
2971 | } |
2972 | |
2973 | /* Wrapper around isl_aff_bind_id for use as pw_aff_locus callback. |
2974 | * "rational" should not be set. |
2975 | */ |
2976 | static __isl_give isl_basic_setisl_basic_map *aff_bind_id(__isl_take isl_aff *aff, |
2977 | int rational, void *user) |
2978 | { |
2979 | isl_id *id = user; |
2980 | |
2981 | if (!aff) |
2982 | return NULL((void*)0); |
2983 | if (rational) |
2984 | isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "rational binding not supported", "polly/lib/External/isl/isl_aff.c" , 2985); goto error; } while (0) |
2985 | "rational binding not supported", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_unsupported , "rational binding not supported", "polly/lib/External/isl/isl_aff.c" , 2985); goto error; } while (0); |
2986 | return isl_aff_bind_id(aff, isl_id_copy(id)); |
2987 | error: |
2988 | isl_aff_free(aff); |
2989 | return NULL((void*)0); |
2990 | } |
2991 | |
2992 | /* Bind the piecewise affine function "pa" to the parameter "id", |
2993 | * returning the elements in the domain where the expression |
2994 | * is equal to the parameter. |
2995 | */ |
2996 | __isl_give isl_setisl_map *isl_pw_aff_bind_id(__isl_take isl_pw_aff *pa, |
2997 | __isl_take isl_id *id) |
2998 | { |
2999 | isl_setisl_map *bound; |
3000 | |
3001 | bound = pw_aff_locus(pa, &aff_bind_id, 0, id); |
3002 | isl_id_free(id); |
3003 | |
3004 | return bound; |
3005 | } |
3006 | |
3007 | /* Return a set containing those elements in the shared domain |
3008 | * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2. |
3009 | * |
3010 | * We compute the difference on the shared domain and then construct |
3011 | * the set of values where this difference is non-negative. |
3012 | * If strict is set, we first subtract 1 from the difference. |
3013 | * If equal is set, we only return the elements where pwaff1 and pwaff2 |
3014 | * are equal. |
3015 | */ |
3016 | static __isl_give isl_setisl_map *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1, |
3017 | __isl_take isl_pw_aff *pwaff2, int strict, int equal) |
3018 | { |
3019 | isl_setisl_map *set1, *set2; |
3020 | |
3021 | set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)); |
3022 | set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)); |
3023 | set1 = isl_set_intersect(set1, set2); |
3024 | pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1)); |
3025 | pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1)); |
3026 | pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2)); |
3027 | |
3028 | if (strict) { |
3029 | isl_space *space = isl_set_get_space(set1); |
3030 | isl_aff *aff; |
3031 | aff = isl_aff_zero_on_domain(isl_local_space_from_space(space)); |
3032 | aff = isl_aff_add_constant_si(aff, -1); |
3033 | pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff)); |
3034 | } else |
3035 | isl_set_free(set1); |
3036 | |
3037 | if (equal) |
3038 | return isl_pw_aff_zero_set(pwaff1); |
3039 | return isl_pw_aff_nonneg_set(pwaff1); |
3040 | } |
3041 | |
3042 | /* Return a set containing those elements in the shared domain |
3043 | * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2. |
3044 | */ |
3045 | __isl_give isl_setisl_map *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1, |
3046 | __isl_take isl_pw_aff *pwaff2) |
3047 | { |
3048 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3049 | return pw_aff_gte_set(pwaff1, pwaff2, 0, 1); |
3050 | } |
3051 | |
3052 | /* Return a set containing those elements in the shared domain |
3053 | * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2. |
3054 | */ |
3055 | __isl_give isl_setisl_map *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1, |
3056 | __isl_take isl_pw_aff *pwaff2) |
3057 | { |
3058 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3059 | return pw_aff_gte_set(pwaff1, pwaff2, 0, 0); |
3060 | } |
3061 | |
3062 | /* Return a set containing those elements in the shared domain |
3063 | * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2. |
3064 | */ |
3065 | __isl_give isl_setisl_map *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1, |
3066 | __isl_take isl_pw_aff *pwaff2) |
3067 | { |
3068 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3069 | return pw_aff_gte_set(pwaff1, pwaff2, 1, 0); |
3070 | } |
3071 | |
3072 | __isl_give isl_setisl_map *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1, |
3073 | __isl_take isl_pw_aff *pwaff2) |
3074 | { |
3075 | return isl_pw_aff_ge_set(pwaff2, pwaff1); |
3076 | } |
3077 | |
3078 | __isl_give isl_setisl_map *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1, |
3079 | __isl_take isl_pw_aff *pwaff2) |
3080 | { |
3081 | return isl_pw_aff_gt_set(pwaff2, pwaff1); |
3082 | } |
3083 | |
3084 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3085 | * where the function values are ordered in the same way as "order", |
3086 | * which returns a set in the shared domain of its two arguments. |
3087 | * |
3088 | * Let "pa1" and "pa2" be defined on domains A and B respectively. |
3089 | * We first pull back the two functions such that they are defined on |
3090 | * the domain [A -> B]. Then we apply "order", resulting in a set |
3091 | * in the space [A -> B]. Finally, we unwrap this set to obtain |
3092 | * a map in the space A -> B. |
3093 | */ |
3094 | static __isl_give isl_map *isl_pw_aff_order_map( |
3095 | __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2, |
3096 | __isl_give isl_setisl_map *(*order)(__isl_take isl_pw_aff *pa1, |
3097 | __isl_take isl_pw_aff *pa2)) |
3098 | { |
3099 | isl_space *space1, *space2; |
3100 | isl_multi_aff *ma; |
3101 | isl_setisl_map *set; |
3102 | |
3103 | isl_pw_aff_align_params_bin(&pa1, &pa2); |
3104 | space1 = isl_space_domain(isl_pw_aff_get_space(pa1)); |
3105 | space2 = isl_space_domain(isl_pw_aff_get_space(pa2)); |
3106 | space1 = isl_space_map_from_domain_and_range(space1, space2); |
3107 | ma = isl_multi_aff_domain_map(isl_space_copy(space1)); |
3108 | pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma); |
3109 | ma = isl_multi_aff_range_map(space1); |
3110 | pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma); |
3111 | set = order(pa1, pa2); |
3112 | |
3113 | return isl_set_unwrap(set); |
3114 | } |
3115 | |
3116 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3117 | * where the function values are equal. |
3118 | */ |
3119 | __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1, |
3120 | __isl_take isl_pw_aff *pa2) |
3121 | { |
3122 | return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_eq_set); |
3123 | } |
3124 | |
3125 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3126 | * where the function value of "pa1" is less than or equal to |
3127 | * the function value of "pa2". |
3128 | */ |
3129 | __isl_give isl_map *isl_pw_aff_le_map(__isl_take isl_pw_aff *pa1, |
3130 | __isl_take isl_pw_aff *pa2) |
3131 | { |
3132 | return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_le_set); |
3133 | } |
3134 | |
3135 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3136 | * where the function value of "pa1" is less than the function value of "pa2". |
3137 | */ |
3138 | __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1, |
3139 | __isl_take isl_pw_aff *pa2) |
3140 | { |
3141 | return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_lt_set); |
3142 | } |
3143 | |
3144 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3145 | * where the function value of "pa1" is greater than or equal to |
3146 | * the function value of "pa2". |
3147 | */ |
3148 | __isl_give isl_map *isl_pw_aff_ge_map(__isl_take isl_pw_aff *pa1, |
3149 | __isl_take isl_pw_aff *pa2) |
3150 | { |
3151 | return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_ge_set); |
3152 | } |
3153 | |
3154 | /* Return a map containing pairs of elements in the domains of "pa1" and "pa2" |
3155 | * where the function value of "pa1" is greater than the function value |
3156 | * of "pa2". |
3157 | */ |
3158 | __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1, |
3159 | __isl_take isl_pw_aff *pa2) |
3160 | { |
3161 | return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_gt_set); |
3162 | } |
3163 | |
3164 | /* Return a set containing those elements in the shared domain |
3165 | * of the elements of list1 and list2 where each element in list1 |
3166 | * has the relation specified by "fn" with each element in list2. |
3167 | */ |
3168 | static __isl_give isl_setisl_map *pw_aff_list_set(__isl_take isl_pw_aff_list *list1, |
3169 | __isl_take isl_pw_aff_list *list2, |
3170 | __isl_give isl_setisl_map *(*fn)(__isl_take isl_pw_aff *pwaff1, |
3171 | __isl_take isl_pw_aff *pwaff2)) |
3172 | { |
3173 | int i, j; |
3174 | isl_ctx *ctx; |
3175 | isl_setisl_map *set; |
3176 | |
3177 | if (!list1 || !list2) |
3178 | goto error; |
3179 | |
3180 | ctx = isl_pw_aff_list_get_ctx(list1); |
3181 | if (list1->n < 1 || list2->n < 1) |
3182 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "list should contain at least one element" , "polly/lib/External/isl/isl_aff.c", 3183); goto error; } while (0) |
3183 | "list should contain at least one element", goto error)do { isl_handle_error(ctx, isl_error_invalid, "list should contain at least one element" , "polly/lib/External/isl/isl_aff.c", 3183); goto error; } while (0); |
3184 | |
3185 | set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0])); |
3186 | for (i = 0; i < list1->n; ++i) |
3187 | for (j = 0; j < list2->n; ++j) { |
3188 | isl_setisl_map *set_ij; |
3189 | |
3190 | set_ij = fn(isl_pw_aff_copy(list1->p[i]), |
3191 | isl_pw_aff_copy(list2->p[j])); |
3192 | set = isl_set_intersect(set, set_ij); |
3193 | } |
3194 | |
3195 | isl_pw_aff_list_free(list1); |
3196 | isl_pw_aff_list_free(list2); |
3197 | return set; |
3198 | error: |
3199 | isl_pw_aff_list_free(list1); |
3200 | isl_pw_aff_list_free(list2); |
3201 | return NULL((void*)0); |
3202 | } |
3203 | |
3204 | /* Return a set containing those elements in the shared domain |
3205 | * of the elements of list1 and list2 where each element in list1 |
3206 | * is equal to each element in list2. |
3207 | */ |
3208 | __isl_give isl_setisl_map *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1, |
3209 | __isl_take isl_pw_aff_list *list2) |
3210 | { |
3211 | return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set); |
3212 | } |
3213 | |
3214 | __isl_give isl_setisl_map *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1, |
3215 | __isl_take isl_pw_aff_list *list2) |
3216 | { |
3217 | return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set); |
3218 | } |
3219 | |
3220 | /* Return a set containing those elements in the shared domain |
3221 | * of the elements of list1 and list2 where each element in list1 |
3222 | * is less than or equal to each element in list2. |
3223 | */ |
3224 | __isl_give isl_setisl_map *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1, |
3225 | __isl_take isl_pw_aff_list *list2) |
3226 | { |
3227 | return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set); |
3228 | } |
3229 | |
3230 | __isl_give isl_setisl_map *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1, |
3231 | __isl_take isl_pw_aff_list *list2) |
3232 | { |
3233 | return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set); |
3234 | } |
3235 | |
3236 | __isl_give isl_setisl_map *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1, |
3237 | __isl_take isl_pw_aff_list *list2) |
3238 | { |
3239 | return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set); |
3240 | } |
3241 | |
3242 | __isl_give isl_setisl_map *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1, |
3243 | __isl_take isl_pw_aff_list *list2) |
3244 | { |
3245 | return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set); |
3246 | } |
3247 | |
3248 | |
3249 | /* Return a set containing those elements in the shared domain |
3250 | * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2. |
3251 | */ |
3252 | __isl_give isl_setisl_map *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1, |
3253 | __isl_take isl_pw_aff *pwaff2) |
3254 | { |
3255 | isl_setisl_map *set_lt, *set_gt; |
3256 | |
3257 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3258 | set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1), |
3259 | isl_pw_aff_copy(pwaff2)); |
3260 | set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2); |
3261 | return isl_set_union_disjoint(set_lt, set_gt); |
3262 | } |
3263 | |
3264 | __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff, |
3265 | isl_int v) |
3266 | { |
3267 | int i; |
3268 | |
3269 | if (isl_int_is_one(v)(isl_sioimath_cmp_si(*(v), 1) == 0)) |
3270 | return pwaff; |
3271 | if (!isl_int_is_pos(v)(isl_sioimath_sgn(*(v)) > 0)) |
3272 | isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,do { isl_handle_error(isl_pw_aff_get_ctx(pwaff), isl_error_invalid , "factor needs to be positive", "polly/lib/External/isl/isl_aff.c" , 3274); return isl_pw_aff_free(pwaff); } while (0) |
3273 | "factor needs to be positive",do { isl_handle_error(isl_pw_aff_get_ctx(pwaff), isl_error_invalid , "factor needs to be positive", "polly/lib/External/isl/isl_aff.c" , 3274); return isl_pw_aff_free(pwaff); } while (0) |
3274 | return isl_pw_aff_free(pwaff))do { isl_handle_error(isl_pw_aff_get_ctx(pwaff), isl_error_invalid , "factor needs to be positive", "polly/lib/External/isl/isl_aff.c" , 3274); return isl_pw_aff_free(pwaff); } while (0); |
3275 | pwaff = isl_pw_aff_cow(pwaff); |
3276 | if (!pwaff) |
3277 | return NULL((void*)0); |
3278 | if (pwaff->n == 0) |
3279 | return pwaff; |
3280 | |
3281 | for (i = 0; i < pwaff->n; ++i) { |
3282 | pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v); |
3283 | if (!pwaff->p[i].aff) |
3284 | return isl_pw_aff_free(pwaff); |
3285 | } |
3286 | |
3287 | return pwaff; |
3288 | } |
3289 | |
3290 | __isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff) |
3291 | { |
3292 | int i; |
3293 | |
3294 | pwaff = isl_pw_aff_cow(pwaff); |
3295 | if (!pwaff) |
3296 | return NULL((void*)0); |
3297 | if (pwaff->n == 0) |
3298 | return pwaff; |
3299 | |
3300 | for (i = 0; i < pwaff->n; ++i) { |
3301 | pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff); |
3302 | if (!pwaff->p[i].aff) |
3303 | return isl_pw_aff_free(pwaff); |
3304 | } |
3305 | |
3306 | return pwaff; |
3307 | } |
3308 | |
3309 | __isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff) |
3310 | { |
3311 | int i; |
3312 | |
3313 | pwaff = isl_pw_aff_cow(pwaff); |
3314 | if (!pwaff) |
3315 | return NULL((void*)0); |
3316 | if (pwaff->n == 0) |
3317 | return pwaff; |
3318 | |
3319 | for (i = 0; i < pwaff->n; ++i) { |
3320 | pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff); |
3321 | if (!pwaff->p[i].aff) |
3322 | return isl_pw_aff_free(pwaff); |
3323 | } |
3324 | |
3325 | return pwaff; |
3326 | } |
3327 | |
3328 | /* Assuming that "cond1" and "cond2" are disjoint, |
3329 | * return an affine expression that is equal to pwaff1 on cond1 |
3330 | * and to pwaff2 on cond2. |
3331 | */ |
3332 | static __isl_give isl_pw_aff *isl_pw_aff_select( |
3333 | __isl_take isl_setisl_map *cond1, __isl_take isl_pw_aff *pwaff1, |
3334 | __isl_take isl_setisl_map *cond2, __isl_take isl_pw_aff *pwaff2) |
3335 | { |
3336 | pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1); |
3337 | pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2); |
3338 | |
3339 | return isl_pw_aff_add_disjoint(pwaff1, pwaff2); |
3340 | } |
3341 | |
3342 | /* Return an affine expression that is equal to pwaff_true for elements |
3343 | * where "cond" is non-zero and to pwaff_false for elements where "cond" |
3344 | * is zero. |
3345 | * That is, return cond ? pwaff_true : pwaff_false; |
3346 | * |
3347 | * If "cond" involves and NaN, then we conservatively return a NaN |
3348 | * on its entire domain. In principle, we could consider the pieces |
3349 | * where it is NaN separately from those where it is not. |
3350 | * |
3351 | * If "pwaff_true" and "pwaff_false" are obviously equal to each other, |
3352 | * then only use the domain of "cond" to restrict the domain. |
3353 | */ |
3354 | __isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond, |
3355 | __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false) |
3356 | { |
3357 | isl_setisl_map *cond_true, *cond_false; |
3358 | isl_bool equal; |
3359 | |
3360 | if (!cond) |
3361 | goto error; |
3362 | if (isl_pw_aff_involves_nan(cond)) { |
3363 | isl_space *space = isl_pw_aff_get_domain_space(cond); |
3364 | isl_local_space *ls = isl_local_space_from_space(space); |
3365 | isl_pw_aff_free(cond); |
3366 | isl_pw_aff_free(pwaff_true); |
3367 | isl_pw_aff_free(pwaff_false); |
3368 | return isl_pw_aff_nan_on_domain(ls); |
3369 | } |
3370 | |
3371 | pwaff_true = isl_pw_aff_align_params(pwaff_true, |
3372 | isl_pw_aff_get_space(pwaff_false)); |
3373 | pwaff_false = isl_pw_aff_align_params(pwaff_false, |
3374 | isl_pw_aff_get_space(pwaff_true)); |
3375 | equal = isl_pw_aff_plain_is_equal(pwaff_true, pwaff_false); |
3376 | if (equal < 0) |
3377 | goto error; |
3378 | if (equal) { |
3379 | isl_setisl_map *dom; |
3380 | |
3381 | dom = isl_set_coalesce(isl_pw_aff_domain(cond)); |
3382 | isl_pw_aff_free(pwaff_false); |
3383 | return isl_pw_aff_intersect_domain(pwaff_true, dom); |
3384 | } |
3385 | |
3386 | cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond)); |
3387 | cond_false = isl_pw_aff_zero_set(cond); |
3388 | return isl_pw_aff_select(cond_true, pwaff_true, |
3389 | cond_false, pwaff_false); |
3390 | error: |
3391 | isl_pw_aff_free(cond); |
3392 | isl_pw_aff_free(pwaff_true); |
3393 | isl_pw_aff_free(pwaff_false); |
3394 | return NULL((void*)0); |
3395 | } |
3396 | |
3397 | isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff) |
3398 | { |
3399 | int pos; |
3400 | |
3401 | if (!aff) |
3402 | return isl_bool_error; |
3403 | |
3404 | pos = isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2); |
3405 | return isl_bool_ok(pos == -1); |
3406 | } |
3407 | |
3408 | /* Check whether pwaff is a piecewise constant. |
3409 | */ |
3410 | isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff) |
3411 | { |
3412 | int i; |
3413 | |
3414 | if (!pwaff) |
3415 | return isl_bool_error; |
3416 | |
3417 | for (i = 0; i < pwaff->n; ++i) { |
3418 | isl_bool is_cst = isl_aff_is_cst(pwaff->p[i].aff); |
3419 | if (is_cst < 0 || !is_cst) |
3420 | return is_cst; |
3421 | } |
3422 | |
3423 | return isl_bool_true; |
3424 | } |
3425 | |
3426 | /* Return the product of "aff1" and "aff2". |
3427 | * |
3428 | * If either of the two is NaN, then the result is NaN. |
3429 | * |
3430 | * Otherwise, at least one of "aff1" or "aff2" needs to be a constant. |
3431 | */ |
3432 | __isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1, |
3433 | __isl_take isl_aff *aff2) |
3434 | { |
3435 | if (!aff1 || !aff2) |
3436 | goto error; |
3437 | |
3438 | if (isl_aff_is_nan(aff1)) { |
3439 | isl_aff_free(aff2); |
3440 | return aff1; |
3441 | } |
3442 | if (isl_aff_is_nan(aff2)) { |
3443 | isl_aff_free(aff1); |
3444 | return aff2; |
3445 | } |
3446 | |
3447 | if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1)) |
3448 | return isl_aff_mul(aff2, aff1); |
3449 | |
3450 | if (!isl_aff_is_cst(aff2)) |
3451 | isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff1), isl_error_invalid , "at least one affine expression should be constant", "polly/lib/External/isl/isl_aff.c" , 3453); goto error; } while (0) |
3452 | "at least one affine expression should be constant",do { isl_handle_error(isl_aff_get_ctx(aff1), isl_error_invalid , "at least one affine expression should be constant", "polly/lib/External/isl/isl_aff.c" , 3453); goto error; } while (0) |
3453 | goto error)do { isl_handle_error(isl_aff_get_ctx(aff1), isl_error_invalid , "at least one affine expression should be constant", "polly/lib/External/isl/isl_aff.c" , 3453); goto error; } while (0); |
3454 | |
3455 | aff1 = isl_aff_cow(aff1); |
3456 | if (!aff1 || !aff2) |
3457 | goto error; |
3458 | |
3459 | aff1 = isl_aff_scale(aff1, aff2->v->el[1]); |
3460 | aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]); |
3461 | |
3462 | isl_aff_free(aff2); |
3463 | return aff1; |
3464 | error: |
3465 | isl_aff_free(aff1); |
3466 | isl_aff_free(aff2); |
3467 | return NULL((void*)0); |
3468 | } |
3469 | |
3470 | /* Divide "aff1" by "aff2", assuming "aff2" is a constant. |
3471 | * |
3472 | * If either of the two is NaN, then the result is NaN. |
3473 | * A division by zero also results in NaN. |
3474 | */ |
3475 | __isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1, |
3476 | __isl_take isl_aff *aff2) |
3477 | { |
3478 | isl_bool is_cst, is_zero; |
3479 | int neg; |
3480 | |
3481 | if (!aff1 || !aff2) |
3482 | goto error; |
3483 | |
3484 | if (isl_aff_is_nan(aff1)) { |
3485 | isl_aff_free(aff2); |
3486 | return aff1; |
3487 | } |
3488 | if (isl_aff_is_nan(aff2)) { |
3489 | isl_aff_free(aff1); |
3490 | return aff2; |
3491 | } |
3492 | |
3493 | is_cst = isl_aff_is_cst(aff2); |
3494 | if (is_cst < 0) |
3495 | goto error; |
3496 | if (!is_cst) |
3497 | isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff2), isl_error_invalid , "second argument should be a constant", "polly/lib/External/isl/isl_aff.c" , 3498); goto error; } while (0) |
3498 | "second argument should be a constant", goto error)do { isl_handle_error(isl_aff_get_ctx(aff2), isl_error_invalid , "second argument should be a constant", "polly/lib/External/isl/isl_aff.c" , 3498); goto error; } while (0); |
3499 | is_zero = isl_aff_plain_is_zero(aff2); |
3500 | if (is_zero < 0) |
3501 | goto error; |
3502 | if (is_zero) |
3503 | return set_nan_free(aff1, aff2); |
3504 | |
3505 | neg = isl_int_is_neg(aff2->v->el[1])(isl_sioimath_sgn(*(aff2->v->el[1])) < 0); |
3506 | if (neg) { |
3507 | isl_int_neg(aff2->v->el[0], aff2->v->el[0])isl_sioimath_neg((aff2->v->el[0]), *(aff2->v->el[ 0])); |
3508 | isl_int_neg(aff2->v->el[1], aff2->v->el[1])isl_sioimath_neg((aff2->v->el[1]), *(aff2->v->el[ 1])); |
3509 | } |
3510 | |
3511 | aff1 = isl_aff_scale(aff1, aff2->v->el[0]); |
3512 | aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]); |
3513 | |
3514 | if (neg) { |
3515 | isl_int_neg(aff2->v->el[0], aff2->v->el[0])isl_sioimath_neg((aff2->v->el[0]), *(aff2->v->el[ 0])); |
3516 | isl_int_neg(aff2->v->el[1], aff2->v->el[1])isl_sioimath_neg((aff2->v->el[1]), *(aff2->v->el[ 1])); |
3517 | } |
3518 | |
3519 | isl_aff_free(aff2); |
3520 | return aff1; |
3521 | error: |
3522 | isl_aff_free(aff1); |
3523 | isl_aff_free(aff2); |
3524 | return NULL((void*)0); |
3525 | } |
3526 | |
3527 | __isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1, |
3528 | __isl_take isl_pw_aff *pwaff2) |
3529 | { |
3530 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3531 | return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add); |
3532 | } |
3533 | |
3534 | __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1, |
3535 | __isl_take isl_pw_aff *pwaff2) |
3536 | { |
3537 | return isl_pw_aff_union_add_(pwaff1, pwaff2); |
3538 | } |
3539 | |
3540 | __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1, |
3541 | __isl_take isl_pw_aff *pwaff2) |
3542 | { |
3543 | isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); |
3544 | return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul); |
3545 | } |
3546 | |
3547 | /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant. |
3548 | */ |
3549 | __isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1, |
3550 | __isl_take isl_pw_aff *pa2) |
3551 | { |
3552 | int is_cst; |
3553 | |
3554 | is_cst = isl_pw_aff_is_cst(pa2); |
3555 | if (is_cst < 0) |
3556 | goto error; |
3557 | if (!is_cst) |
3558 | isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3560); goto error; } while (0) |
3559 | "second argument should be a piecewise constant",do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3560); goto error; } while (0) |
3560 | goto error)do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3560); goto error; } while (0); |
3561 | isl_pw_aff_align_params_bin(&pa1, &pa2); |
3562 | return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div); |
3563 | error: |
3564 | isl_pw_aff_free(pa1); |
3565 | isl_pw_aff_free(pa2); |
3566 | return NULL((void*)0); |
3567 | } |
3568 | |
3569 | /* Compute the quotient of the integer division of "pa1" by "pa2" |
3570 | * with rounding towards zero. |
3571 | * "pa2" is assumed to be a piecewise constant. |
3572 | * |
3573 | * In particular, return |
3574 | * |
3575 | * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2) |
3576 | * |
3577 | */ |
3578 | __isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1, |
3579 | __isl_take isl_pw_aff *pa2) |
3580 | { |
3581 | int is_cst; |
3582 | isl_setisl_map *cond; |
3583 | isl_pw_aff *f, *c; |
3584 | |
3585 | is_cst = isl_pw_aff_is_cst(pa2); |
3586 | if (is_cst < 0) |
3587 | goto error; |
3588 | if (!is_cst) |
3589 | isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3591); goto error; } while (0) |
3590 | "second argument should be a piecewise constant",do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3591); goto error; } while (0) |
3591 | goto error)do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3591); goto error; } while (0); |
3592 | |
3593 | pa1 = isl_pw_aff_div(pa1, pa2); |
3594 | |
3595 | cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1)); |
3596 | f = isl_pw_aff_floor(isl_pw_aff_copy(pa1)); |
3597 | c = isl_pw_aff_ceil(pa1); |
3598 | return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c); |
3599 | error: |
3600 | isl_pw_aff_free(pa1); |
3601 | isl_pw_aff_free(pa2); |
3602 | return NULL((void*)0); |
3603 | } |
3604 | |
3605 | /* Compute the remainder of the integer division of "pa1" by "pa2" |
3606 | * with rounding towards zero. |
3607 | * "pa2" is assumed to be a piecewise constant. |
3608 | * |
3609 | * In particular, return |
3610 | * |
3611 | * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)) |
3612 | * |
3613 | */ |
3614 | __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1, |
3615 | __isl_take isl_pw_aff *pa2) |
3616 | { |
3617 | int is_cst; |
3618 | isl_pw_aff *res; |
3619 | |
3620 | is_cst = isl_pw_aff_is_cst(pa2); |
3621 | if (is_cst < 0) |
3622 | goto error; |
3623 | if (!is_cst) |
3624 | isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3626); goto error; } while (0) |
3625 | "second argument should be a piecewise constant",do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3626); goto error; } while (0) |
3626 | goto error)do { isl_handle_error(isl_pw_aff_get_ctx(pa2), isl_error_invalid , "second argument should be a piecewise constant", "polly/lib/External/isl/isl_aff.c" , 3626); goto error; } while (0); |
3627 | res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2)); |
3628 | res = isl_pw_aff_mul(pa2, res); |
3629 | res = isl_pw_aff_sub(pa1, res); |
3630 | return res; |
3631 | error: |
3632 | isl_pw_aff_free(pa1); |
3633 | isl_pw_aff_free(pa2); |
3634 | return NULL((void*)0); |
3635 | } |
3636 | |
3637 | /* Does either of "pa1" or "pa2" involve any NaN2? |
3638 | */ |
3639 | static isl_bool either_involves_nan(__isl_keep isl_pw_aff *pa1, |
3640 | __isl_keep isl_pw_aff *pa2) |
3641 | { |
3642 | isl_bool has_nan; |
3643 | |
3644 | has_nan = isl_pw_aff_involves_nan(pa1); |
3645 | if (has_nan < 0 || has_nan) |
3646 | return has_nan; |
3647 | return isl_pw_aff_involves_nan(pa2); |
3648 | } |
3649 | |
3650 | /* Replace "pa1" and "pa2" (at least one of which involves a NaN) |
3651 | * by a NaN on their shared domain. |
3652 | * |
3653 | * In principle, the result could be refined to only being NaN |
3654 | * on the parts of this domain where at least one of "pa1" or "pa2" is NaN. |
3655 | */ |
3656 | static __isl_give isl_pw_aff *replace_by_nan(__isl_take isl_pw_aff *pa1, |
3657 | __isl_take isl_pw_aff *pa2) |
3658 | { |
3659 | isl_local_space *ls; |
3660 | isl_setisl_map *dom; |
3661 | isl_pw_aff *pa; |
3662 | |
3663 | dom = isl_set_intersect(isl_pw_aff_domain(pa1), isl_pw_aff_domain(pa2)); |
3664 | ls = isl_local_space_from_space(isl_set_get_space(dom)); |
3665 | pa = isl_pw_aff_nan_on_domain(ls); |
3666 | pa = isl_pw_aff_intersect_domain(pa, dom); |
3667 | |
3668 | return pa; |
3669 | } |
3670 | |
3671 | static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1, |
3672 | __isl_take isl_pw_aff *pwaff2) |
3673 | { |
3674 | isl_setisl_map *le; |
3675 | isl_setisl_map *dom; |
3676 | |
3677 | dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)), |
3678 | isl_pw_aff_domain(isl_pw_aff_copy(pwaff2))); |
3679 | le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1), |
3680 | isl_pw_aff_copy(pwaff2)); |
3681 | dom = isl_set_subtract(dom, isl_set_copy(le)); |
3682 | return isl_pw_aff_select(le, pwaff1, dom, pwaff2); |
3683 | } |
3684 | |
3685 | static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1, |
3686 | __isl_take isl_pw_aff *pwaff2) |
3687 | { |
3688 | isl_setisl_map *ge; |
3689 | isl_setisl_map *dom; |
3690 | |
3691 | dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)), |
3692 | isl_pw_aff_domain(isl_pw_aff_copy(pwaff2))); |
3693 | ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1), |
3694 | isl_pw_aff_copy(pwaff2)); |
3695 | dom = isl_set_subtract(dom, isl_set_copy(ge)); |
3696 | return isl_pw_aff_select(ge, pwaff1, dom, pwaff2); |
3697 | } |
3698 | |
3699 | /* Return an expression for the minimum (if "max" is not set) or |
3700 | * the maximum (if "max" is set) of "pa1" and "pa2". |
3701 | * If either expression involves any NaN, then return a NaN |
3702 | * on the shared domain as result. |
3703 | */ |
3704 | static __isl_give isl_pw_aff *pw_aff_min_max(__isl_take isl_pw_aff *pa1, |
3705 | __isl_take isl_pw_aff *pa2, int max) |
3706 | { |
3707 | isl_bool has_nan; |
3708 | |
3709 | has_nan = either_involves_nan(pa1, pa2); |
3710 | if (has_nan < 0) |
3711 | pa1 = isl_pw_aff_free(pa1); |
3712 | else if (has_nan) |
3713 | return replace_by_nan(pa1, pa2); |
3714 | |
3715 | isl_pw_aff_align_params_bin(&pa1, &pa2); |
3716 | if (max) |
3717 | return pw_aff_max(pa1, pa2); |
3718 | else |
3719 | return pw_aff_min(pa1, pa2); |
3720 | } |
3721 | |
3722 | /* Return an expression for the minimum of "pwaff1" and "pwaff2". |
3723 | */ |
3724 | __isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1, |
3725 | __isl_take isl_pw_aff *pwaff2) |
3726 | { |
3727 | return pw_aff_min_max(pwaff1, pwaff2, 0); |
3728 | } |
3729 | |
3730 | /* Return an expression for the maximum of "pwaff1" and "pwaff2". |
3731 | */ |
3732 | __isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1, |
3733 | __isl_take isl_pw_aff *pwaff2) |
3734 | { |
3735 | return pw_aff_min_max(pwaff1, pwaff2, 1); |
3736 | } |
3737 | |
3738 | static __isl_give isl_pw_aff *pw_aff_list_reduce( |
3739 | __isl_take isl_pw_aff_list *list, |
3740 | __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1, |
3741 | __isl_take isl_pw_aff *pwaff2)) |
3742 | { |
3743 | int i; |
3744 | isl_ctx *ctx; |
3745 | isl_pw_aff *res; |
3746 | |
3747 | if (!list) |
3748 | return NULL((void*)0); |
3749 | |
3750 | ctx = isl_pw_aff_list_get_ctx(list); |
3751 | if (list->n < 1) |
3752 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "list should contain at least one element" , "polly/lib/External/isl/isl_aff.c", 3753); goto error; } while (0) |
3753 | "list should contain at least one element", goto error)do { isl_handle_error(ctx, isl_error_invalid, "list should contain at least one element" , "polly/lib/External/isl/isl_aff.c", 3753); goto error; } while (0); |
3754 | |
3755 | res = isl_pw_aff_copy(list->p[0]); |
3756 | for (i = 1; i < list->n; ++i) |
3757 | res = fn(res, isl_pw_aff_copy(list->p[i])); |
3758 | |
3759 | isl_pw_aff_list_free(list); |
3760 | return res; |
3761 | error: |
3762 | isl_pw_aff_list_free(list); |
3763 | return NULL((void*)0); |
3764 | } |
3765 | |
3766 | /* Return an isl_pw_aff that maps each element in the intersection of the |
3767 | * domains of the elements of list to the minimal corresponding affine |
3768 | * expression. |
3769 | */ |
3770 | __isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list) |
3771 | { |
3772 | return pw_aff_list_reduce(list, &isl_pw_aff_min); |
3773 | } |
3774 | |
3775 | /* Return an isl_pw_aff that maps each element in the intersection of the |
3776 | * domains of the elements of list to the maximal corresponding affine |
3777 | * expression. |
3778 | */ |
3779 | __isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list) |
3780 | { |
3781 | return pw_aff_list_reduce(list, &isl_pw_aff_max); |
3782 | } |
3783 | |
3784 | /* Mark the domains of "pwaff" as rational. |
3785 | */ |
3786 | __isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff) |
3787 | { |
3788 | int i; |
3789 | |
3790 | pwaff = isl_pw_aff_cow(pwaff); |
3791 | if (!pwaff) |
3792 | return NULL((void*)0); |
3793 | if (pwaff->n == 0) |
3794 | return pwaff; |
3795 | |
3796 | for (i = 0; i < pwaff->n; ++i) { |
3797 | pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set); |
3798 | if (!pwaff->p[i].set) |
3799 | return isl_pw_aff_free(pwaff); |
3800 | } |
3801 | |
3802 | return pwaff; |
3803 | } |
3804 | |
3805 | /* Mark the domains of the elements of "list" as rational. |
3806 | */ |
3807 | __isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational( |
3808 | __isl_take isl_pw_aff_list *list) |
3809 | { |
3810 | int i, n; |
3811 | |
3812 | if (!list) |
3813 | return NULL((void*)0); |
3814 | if (list->n == 0) |
3815 | return list; |
3816 | |
3817 | n = list->n; |
3818 | for (i = 0; i < n; ++i) { |
3819 | isl_pw_aff *pa; |
3820 | |
3821 | pa = isl_pw_aff_list_get_pw_aff(list, i); |
3822 | pa = isl_pw_aff_set_rational(pa); |
3823 | list = isl_pw_aff_list_set_pw_aff(list, i, pa); |
3824 | } |
3825 | |
3826 | return list; |
3827 | } |
3828 | |
3829 | /* Do the parameters of "aff" match those of "space"? |
3830 | */ |
3831 | isl_bool isl_aff_matching_params(__isl_keep isl_aff *aff, |
3832 | __isl_keep isl_space *space) |
3833 | { |
3834 | isl_space *aff_space; |
3835 | isl_bool match; |
3836 | |
3837 | if (!aff || !space) |
3838 | return isl_bool_error; |
3839 | |
3840 | aff_space = isl_aff_get_domain_space(aff); |
3841 | |
3842 | match = isl_space_has_equal_params(space, aff_space); |
3843 | |
3844 | isl_space_free(aff_space); |
3845 | return match; |
3846 | } |
3847 | |
3848 | /* Check that the domain space of "aff" matches "space". |
3849 | */ |
3850 | isl_stat isl_aff_check_match_domain_space(__isl_keep isl_aff *aff, |
3851 | __isl_keep isl_space *space) |
3852 | { |
3853 | isl_space *aff_space; |
3854 | isl_bool match; |
3855 | |
3856 | if (!aff || !space) |
3857 | return isl_stat_error; |
3858 | |
3859 | aff_space = isl_aff_get_domain_space(aff); |
3860 | |
3861 | match = isl_space_has_equal_params(space, aff_space); |
3862 | if (match < 0) |
3863 | goto error; |
3864 | if (!match) |
3865 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "parameters don't match", "polly/lib/External/isl/isl_aff.c" , 3866); goto error; } while (0) |
3866 | "parameters don't match", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "parameters don't match", "polly/lib/External/isl/isl_aff.c" , 3866); goto error; } while (0); |
3867 | match = isl_space_tuple_is_equal(space, isl_dim_in, |
3868 | aff_space, isl_dim_set); |
3869 | if (match < 0) |
3870 | goto error; |
3871 | if (!match) |
3872 | isl_die(isl_aff_get_ctx(aff), isl_error_invalid,do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "domains don't match", "polly/lib/External/isl/isl_aff.c", 3873 ); goto error; } while (0) |
3873 | "domains don't match", goto error)do { isl_handle_error(isl_aff_get_ctx(aff), isl_error_invalid , "domains don't match", "polly/lib/External/isl/isl_aff.c", 3873 ); goto error; } while (0); |
3874 | isl_space_free(aff_space); |
3875 | return isl_stat_ok; |
3876 | error: |
3877 | isl_space_free(aff_space); |
3878 | return isl_stat_error; |
3879 | } |
3880 | |
3881 | /* Return the shared (universe) domain of the elements of "ma". |
3882 | * |
3883 | * Since an isl_multi_aff (and an isl_aff) is always total, |
3884 | * the domain is always the universe set in its domain space. |
3885 | * This is a helper function for use in the generic isl_multi_*_bind. |
3886 | */ |
3887 | static __isl_give isl_basic_setisl_basic_map *isl_multi_aff_domain( |
3888 | __isl_take isl_multi_aff *ma) |
3889 | { |
3890 | isl_space *space; |
3891 | |
3892 | space = isl_multi_aff_get_space(ma); |
3893 | isl_multi_aff_free(ma); |
3894 | |
3895 | return isl_basic_set_universe(isl_space_domain(space)); |
3896 | } |
3897 | |
3898 | #undef BASEunion_pw_aff |
3899 | #define BASEunion_pw_aff aff |
3900 | |
3901 | #include <isl_multi_no_explicit_domain.c> |
3902 | #include <isl_multi_templ.c> |
3903 | #include <isl_multi_add_constant_templ.c> |
3904 | #include <isl_multi_apply_set.c> |
3905 | #include <isl_multi_arith_templ.c> |
3906 | #include <isl_multi_bind_domain_templ.c> |
3907 | #include <isl_multi_cmp.c> |
3908 | #include <isl_multi_dim_id_templ.c> |
3909 | #include <isl_multi_dims.c> |
3910 | #include <isl_multi_floor.c> |
3911 | #include <isl_multi_from_base_templ.c> |
3912 | #include <isl_multi_identity_templ.c> |
3913 | #include <isl_multi_insert_domain_templ.c> |
3914 | #include <isl_multi_locals_templ.c> |
3915 | #include <isl_multi_move_dims_templ.c> |
3916 | #include <isl_multi_nan_templ.c> |
3917 | #include <isl_multi_product_templ.c> |
3918 | #include <isl_multi_splice_templ.c> |
3919 | #include <isl_multi_tuple_id_templ.c> |
3920 | #include <isl_multi_unbind_params_templ.c> |
3921 | #include <isl_multi_zero_templ.c> |
3922 | |
3923 | #undef DOMBASEunion_set |
3924 | #define DOMBASEunion_set set |
3925 | #include <isl_multi_gist.c> |
3926 | |
3927 | #undef DOMBASEunion_set |
3928 | #define DOMBASEunion_set basic_set |
3929 | #include <isl_multi_bind_templ.c> |
3930 | |
3931 | /* Construct an isl_multi_aff living in "space" that corresponds |
3932 | * to the affine transformation matrix "mat". |
3933 | */ |
3934 | __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat( |
3935 | __isl_take isl_space *space, __isl_take isl_mat *mat) |
3936 | { |
3937 | isl_ctx *ctx; |
3938 | isl_local_space *ls = NULL((void*)0); |
3939 | isl_multi_aff *ma = NULL((void*)0); |
3940 | isl_size n_row, n_col, n_out, total; |
3941 | int i; |
3942 | |
3943 | if (!space || !mat) |
3944 | goto error; |
3945 | |
3946 | ctx = isl_mat_get_ctx(mat); |
3947 | |
3948 | n_row = isl_mat_rows(mat); |
3949 | n_col = isl_mat_cols(mat); |
3950 | n_out = isl_space_dim(space, isl_dim_out); |
3951 | total = isl_space_dim(space, isl_dim_all); |
3952 | if (n_row < 0 || n_col < 0 || n_out < 0 || total < 0) |
3953 | goto error; |
3954 | if (n_row < 1) |
3955 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "insufficient number of rows" , "polly/lib/External/isl/isl_aff.c", 3956); goto error; } while (0) |
3956 | "insufficient number of rows", goto error)do { isl_handle_error(ctx, isl_error_invalid, "insufficient number of rows" , "polly/lib/External/isl/isl_aff.c", 3956); goto error; } while (0); |
3957 | if (n_col < 1) |
3958 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "insufficient number of columns" , "polly/lib/External/isl/isl_aff.c", 3959); goto error; } while (0) |
3959 | "insufficient number of columns", goto error)do { isl_handle_error(ctx, isl_error_invalid, "insufficient number of columns" , "polly/lib/External/isl/isl_aff.c", 3959); goto error; } while (0); |
3960 | if (1 + n_out != n_row || 2 + total != n_row + n_col) |
3961 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "dimension mismatch" , "polly/lib/External/isl/isl_aff.c", 3962); goto error; } while (0) |
3962 | "dimension mismatch", goto error)do { isl_handle_error(ctx, isl_error_invalid, "dimension mismatch" , "polly/lib/External/isl/isl_aff.c", 3962); goto error; } while (0); |
3963 | |
3964 | ma = isl_multi_aff_zero(isl_space_copy(space)); |
3965 | space = isl_space_domain(space); |
3966 | ls = isl_local_space_from_space(isl_space_copy(space)); |
3967 | |
3968 | for (i = 0; i < n_row - 1; ++i) { |
3969 | isl_vec *v; |
3970 | isl_aff *aff; |
3971 | |
3972 | v = isl_vec_alloc(ctx, 1 + n_col); |
3973 | if (!v) |
3974 | goto error; |
3975 | isl_int_set(v->el[0], mat->row[0][0])isl_sioimath_set((v->el[0]), *(mat->row[0][0])); |
3976 | isl_seq_cpy(v->el + 1, mat->row[1 + i], n_col); |
3977 | v = isl_vec_normalize(v); |
3978 | aff = isl_aff_alloc_vec(isl_local_space_copy(ls), v); |
3979 | ma = isl_multi_aff_set_aff(ma, i, aff); |
3980 | } |
3981 | |
3982 | isl_space_free(space); |
3983 | isl_local_space_free(ls); |
3984 | isl_mat_free(mat); |
3985 | return ma; |
3986 | error: |
3987 | isl_space_free(space); |
3988 | isl_local_space_free(ls); |
3989 | isl_mat_free(mat); |
3990 | isl_multi_aff_free(ma); |
3991 | return NULL((void*)0); |
3992 | } |
3993 | |
3994 | /* Return the constant terms of the affine expressions of "ma". |
3995 | */ |
3996 | __isl_give isl_multi_val *isl_multi_aff_get_constant_multi_val( |
3997 | __isl_keep isl_multi_aff *ma) |
3998 | { |
3999 | int i; |
4000 | isl_size n; |
4001 | isl_space *space; |
4002 | isl_multi_val *mv; |
4003 | |
4004 | n = isl_multi_aff_size(ma); |
4005 | if (n < 0) |
4006 | return NULL((void*)0); |
4007 | space = isl_space_range(isl_multi_aff_get_space(ma)); |
4008 | space = isl_space_drop_all_params(space); |
4009 | mv = isl_multi_val_zero(space); |
4010 | |
4011 | for (i = 0; i < n; ++i) { |
4012 | isl_aff *aff; |
4013 | isl_val *val; |
4014 | |
4015 | aff = isl_multi_aff_get_at(ma, i); |
4016 | val = isl_aff_get_constant_val(aff); |
4017 | isl_aff_free(aff); |
4018 | mv = isl_multi_val_set_at(mv, i, val); |
4019 | } |
4020 | |
4021 | return mv; |
4022 | } |
4023 | |
4024 | /* Remove any internal structure of the domain of "ma". |
4025 | * If there is any such internal structure in the input, |
4026 | * then the name of the corresponding space is also removed. |
4027 | */ |
4028 | __isl_give isl_multi_aff *isl_multi_aff_flatten_domain( |
4029 | __isl_take isl_multi_aff *ma) |
4030 | { |
4031 | isl_space *space; |
4032 | |
4033 | if (!ma) |
4034 | return NULL((void*)0); |
4035 | |
4036 | if (!ma->space->nested[0]) |
4037 | return ma; |
4038 | |
4039 | space = isl_multi_aff_get_space(ma); |
4040 | space = isl_space_flatten_domain(space); |
4041 | ma = isl_multi_aff_reset_space(ma, space); |
4042 | |
4043 | return ma; |
4044 | } |
4045 | |
4046 | /* Given a map space, return an isl_multi_aff that maps a wrapped copy |
4047 | * of the space to its domain. |
4048 | */ |
4049 | __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space) |
4050 | { |
4051 | int i; |
4052 | isl_size n_in; |
4053 | isl_local_space *ls; |
4054 | isl_multi_aff *ma; |
4055 | |
4056 | if (!space) |
4057 | return NULL((void*)0); |
4058 | if (!isl_space_is_map(space)) |
4059 | isl_die(isl_space_get_ctx(space), isl_error_invalid,do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "not a map space", "polly/lib/External/isl/isl_aff.c", 4060 ); goto error; } while (0) |
4060 | "not a map space", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "not a map space", "polly/lib/External/isl/isl_aff.c", 4060 ); goto error; } while (0); |
4061 | |
4062 | n_in = isl_space_dim(space, isl_dim_in); |
4063 | if (n_in < 0) |
4064 | goto error; |
4065 | space = isl_space_domain_map(space); |
4066 | |
4067 | ma = isl_multi_aff_alloc(isl_space_copy(space)); |
4068 | if (n_in == 0) { |
4069 | isl_space_free(space); |
4070 | return ma; |
4071 | } |
4072 | |
4073 | space = isl_space_domain(space); |
4074 | ls = isl_local_space_from_space(space); |
4075 | for (i = 0; i < n_in; ++i) { |
4076 | isl_aff *aff; |
4077 | |
4078 | aff = isl_aff_var_on_domain(isl_local_space_copy(ls), |
4079 | isl_dim_set, i); |
4080 | ma = isl_multi_aff_set_aff(ma, i, aff); |
4081 | } |
4082 | isl_local_space_free(ls); |
4083 | return ma; |
4084 | error: |
4085 | isl_space_free(space); |
4086 | return NULL((void*)0); |
4087 | } |
4088 | |
4089 | /* This function performs the same operation as isl_multi_aff_domain_map, |
4090 | * but is considered as a function on an isl_space when exported. |
4091 | */ |
4092 | __isl_give isl_multi_aff *isl_space_domain_map_multi_aff( |
4093 | __isl_take isl_space *space) |
4094 | { |
4095 | return isl_multi_aff_domain_map(space); |
4096 | } |
4097 | |
4098 | /* Given a map space, return an isl_multi_aff that maps a wrapped copy |
4099 | * of the space to its range. |
4100 | */ |
4101 | __isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space) |
4102 | { |
4103 | int i; |
4104 | isl_size n_in, n_out; |
4105 | isl_local_space *ls; |
4106 | isl_multi_aff *ma; |
4107 | |
4108 | if (!space) |
4109 | return NULL((void*)0); |
4110 | if (!isl_space_is_map(space)) |
4111 | isl_die(isl_space_get_ctx(space), isl_error_invalid,do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "not a map space", "polly/lib/External/isl/isl_aff.c", 4112 ); goto error; } while (0) |
4112 | "not a map space", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "not a map space", "polly/lib/External/isl/isl_aff.c", 4112 ); goto error; } while (0); |
4113 | |
4114 | n_in = isl_space_dim(space, isl_dim_in); |
4115 | n_out = isl_space_dim(space, isl_dim_out); |
4116 | if (n_in < 0 || n_out < 0) |
4117 | goto error; |
4118 | space = isl_space_range_map(space); |
4119 | |
4120 | ma = isl_multi_aff_alloc(isl_space_copy(space)); |
4121 | if (n_out == 0) { |
4122 | isl_space_free(space); |
4123 | return ma; |
4124 | } |
4125 | |
4126 | space = isl_space_domain(space); |
4127 | ls = isl_local_space_from_space(space); |
4128 | for (i = 0; i < n_out; ++i) { |
4129 | isl_aff *aff; |
4130 | |
4131 | aff = isl_aff_var_on_domain(isl_local_space_copy(ls), |
4132 | isl_dim_set, n_in + i); |
4133 | ma = isl_multi_aff_set_aff(ma, i, aff); |
4134 | } |
4135 | isl_local_space_free(ls); |
4136 | return ma; |
4137 | error: |
4138 | isl_space_free(space); |
4139 | return NULL((void*)0); |
4140 | } |
4141 | |
4142 | /* This function performs the same operation as isl_multi_aff_range_map, |
4143 | * but is considered as a function on an isl_space when exported. |
4144 | */ |
4145 | __isl_give isl_multi_aff *isl_space_range_map_multi_aff( |
4146 | __isl_take isl_space *space) |
4147 | { |
4148 | return isl_multi_aff_range_map(space); |
4149 | } |
4150 | |
4151 | /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy |
4152 | * of the space to its domain. |
4153 | */ |
4154 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_domain_map( |
4155 | __isl_take isl_space *space) |
4156 | { |
4157 | return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_domain_map(space)); |
4158 | } |
4159 | |
4160 | /* This function performs the same operation as isl_pw_multi_aff_domain_map, |
4161 | * but is considered as a function on an isl_space when exported. |
4162 | */ |
4163 | __isl_give isl_pw_multi_aff *isl_space_domain_map_pw_multi_aff( |
4164 | __isl_take isl_space *space) |
4165 | { |
4166 | return isl_pw_multi_aff_domain_map(space); |
4167 | } |
4168 | |
4169 | /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy |
4170 | * of the space to its range. |
4171 | */ |
4172 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map( |
4173 | __isl_take isl_space *space) |
4174 | { |
4175 | return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space)); |
4176 | } |
4177 | |
4178 | /* This function performs the same operation as isl_pw_multi_aff_range_map, |
4179 | * but is considered as a function on an isl_space when exported. |
4180 | */ |
4181 | __isl_give isl_pw_multi_aff *isl_space_range_map_pw_multi_aff( |
4182 | __isl_take isl_space *space) |
4183 | { |
4184 | return isl_pw_multi_aff_range_map(space); |
4185 | } |
4186 | |
4187 | /* Given the space of a set and a range of set dimensions, |
4188 | * construct an isl_multi_aff that projects out those dimensions. |
4189 | */ |
4190 | __isl_give isl_multi_aff *isl_multi_aff_project_out_map( |
4191 | __isl_take isl_space *space, enum isl_dim_type type, |
4192 | unsigned first, unsigned n) |
4193 | { |
4194 | int i; |
4195 | isl_size dim; |
4196 | isl_local_space *ls; |
4197 | isl_multi_aff *ma; |
4198 | |
4199 | if (!space) |
4200 | return NULL((void*)0); |
4201 | if (!isl_space_is_set(space)) |
4202 | isl_die(isl_space_get_ctx(space), isl_error_unsupported,do { isl_handle_error(isl_space_get_ctx(space), isl_error_unsupported , "expecting set space", "polly/lib/External/isl/isl_aff.c", 4203 ); goto error; } while (0) |
4203 | "expecting set space", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_unsupported , "expecting set space", "polly/lib/External/isl/isl_aff.c", 4203 ); goto error; } while (0); |
4204 | if (type != isl_dim_set) |
4205 | isl_die(isl_space_get_ctx(space), isl_error_invalid,do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "only set dimensions can be projected out", "polly/lib/External/isl/isl_aff.c" , 4206); goto error; } while (0) |
4206 | "only set dimensions can be projected out", goto error)do { isl_handle_error(isl_space_get_ctx(space), isl_error_invalid , "only set dimensions can be projected out", "polly/lib/External/isl/isl_aff.c" , 4206); goto error; } while (0); |
4207 | if (isl_space_check_range(space, type, first, n) < 0) |
4208 | goto error; |
4209 | |
4210 | dim = isl_space_dim(space, isl_dim_set); |
4211 | if (dim < 0) |
4212 | goto error; |
4213 | |
4214 | space = isl_space_from_domain(space); |
4215 | space = isl_space_add_dims(space, isl_dim_out, dim - n); |
4216 | |
4217 | if (dim == n) |
4218 | return isl_multi_aff_alloc(space); |
4219 | |
4220 | ma = isl_multi_aff_alloc(isl_space_copy(space)); |
4221 | space = isl_space_domain(space); |
4222 | ls = isl_local_space_from_space(space); |
4223 | |
4224 | for (i = 0; i < first; ++i) { |
4225 | isl_aff *aff; |
4226 | |
4227 | aff = isl_aff_var_on_domain(isl_local_space_copy(ls), |
4228 | isl_dim_set, i); |
4229 | ma = isl_multi_aff_set_aff(ma, i, aff); |
4230 | } |
4231 | |
4232 | for (i = 0; i < dim - (first + n); ++i) { |
4233 | isl_aff *aff; |
4234 | |
4235 | aff = isl_aff_var_on_domain(isl_local_space_copy(ls), |
4236 | isl_dim_set, first + n + i); |
4237 | ma = isl_multi_aff_set_aff(ma, first + i, aff); |
4238 | } |
4239 | |
4240 | isl_local_space_free(ls); |
4241 | return ma; |
4242 | error: |
4243 | isl_space_free(space); |
4244 | return NULL((void*)0); |
4245 | } |
4246 | |
4247 | /* Given the space of a set and a range of set dimensions, |
4248 | * construct an isl_pw_multi_aff that projects out those dimensions. |
4249 | */ |
4250 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map( |
4251 | __isl_take isl_space *space, enum isl_dim_type type, |
4252 | unsigned first, unsigned n) |
4253 | { |
4254 | isl_multi_aff *ma; |
4255 | |
4256 | ma = isl_multi_aff_project_out_map(space, type, first, n); |
4257 | return isl_pw_multi_aff_from_multi_aff(ma); |
4258 | } |
4259 | |
4260 | /* This function performs the same operation as isl_pw_multi_aff_from_multi_aff, |
4261 | * but is considered as a function on an isl_multi_aff when exported. |
4262 | */ |
4263 | __isl_give isl_pw_multi_aff *isl_multi_aff_to_pw_multi_aff( |
4264 | __isl_take isl_multi_aff *ma) |
4265 | { |
4266 | return isl_pw_multi_aff_from_multi_aff(ma); |
4267 | } |
4268 | |
4269 | /* Create a piecewise multi-affine expression in the given space that maps each |
4270 | * input dimension to the corresponding output dimension. |
4271 | */ |
4272 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity( |
4273 | __isl_take isl_space *space) |
4274 | { |
4275 | return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space)); |
4276 | } |
4277 | |
4278 | /* Create a piecewise multi expression that maps elements in the given space |
4279 | * to themselves. |
4280 | */ |
4281 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity_on_domain_space( |
4282 | __isl_take isl_space *space) |
4283 | { |
4284 | isl_multi_aff *ma; |
4285 | |
4286 | ma = isl_multi_aff_identity_on_domain_space(space); |
4287 | return isl_pw_multi_aff_from_multi_aff(ma); |
4288 | } |
4289 | |
4290 | /* This function performs the same operation as |
4291 | * isl_pw_multi_aff_identity_on_domain_space, |
4292 | * but is considered as a function on an isl_space when exported. |
4293 | */ |
4294 | __isl_give isl_pw_multi_aff *isl_space_identity_pw_multi_aff_on_domain( |
4295 | __isl_take isl_space *space) |
4296 | { |
4297 | return isl_pw_multi_aff_identity_on_domain_space(space); |
4298 | } |
4299 | |
4300 | /* Exploit the equalities in "eq" to simplify the affine expressions. |
4301 | */ |
4302 | static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities( |
4303 | __isl_take isl_multi_aff *maff, __isl_take isl_basic_setisl_basic_map *eq) |
4304 | { |
4305 | int i; |
4306 | |
4307 | maff = isl_multi_aff_cow(maff); |
4308 | if (!maff || !eq) |
4309 | goto error; |
4310 | |
4311 | for (i = 0; i < maff->n; ++i) { |
4312 | maff->u.p[i] = isl_aff_substitute_equalities(maff->u.p[i], |
4313 | isl_basic_set_copy(eq)); |
4314 | if (!maff->u.p[i]) |
4315 | goto error; |
4316 | } |
4317 | |
4318 | isl_basic_set_free(eq); |
4319 | return maff; |
4320 | error: |
4321 | isl_basic_set_free(eq); |
4322 | isl_multi_aff_free(maff); |
4323 | return NULL((void*)0); |
4324 | } |
4325 | |
4326 | __isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff, |
4327 | isl_int f) |
4328 | { |
4329 | int i; |
4330 | |
4331 | maff = isl_multi_aff_cow(maff); |
4332 | if (!maff) |
4333 | return NULL((void*)0); |
4334 | |
4335 | for (i = 0; i < maff->n; ++i) { |
4336 | maff->u.p[i] = isl_aff_scale(maff->u.p[i], f); |
4337 | if (!maff->u.p[i]) |
4338 | return isl_multi_aff_free(maff); |
4339 | } |
4340 | |
4341 | return maff; |
4342 | } |
4343 | |
4344 | __isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_setisl_map *dom, |
4345 | __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2) |
4346 | { |
4347 | maff1 = isl_multi_aff_add(maff1, maff2); |
4348 | maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom)); |
4349 | return maff1; |
4350 | } |
4351 | |
4352 | isl_bool isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff) |
4353 | { |
4354 | if (!maff) |
4355 | return isl_bool_error; |
4356 | |
4357 | return isl_bool_false; |
4358 | } |
4359 | |
4360 | /* Return the set of domain elements where "ma1" is lexicographically |
4361 | * smaller than or equal to "ma2". |
4362 | */ |
4363 | __isl_give isl_setisl_map *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1, |
4364 | __isl_take isl_multi_aff *ma2) |
4365 | { |
4366 | return isl_multi_aff_lex_ge_set(ma2, ma1); |
4367 | } |
4368 | |
4369 | /* Return the set of domain elements where "ma1" is lexicographically |
4370 | * smaller than "ma2". |
4371 | */ |
4372 | __isl_give isl_setisl_map *isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff *ma1, |
4373 | __isl_take isl_multi_aff *ma2) |
4374 | { |
4375 | return isl_multi_aff_lex_gt_set(ma2, ma1); |
4376 | } |
4377 | |
4378 | /* Return the set of domain elements where "ma1" is lexicographically |
4379 | * greater than to "ma2". If "equal" is set, then include the domain |
4380 | * elements where they are equal. |
4381 | * Do this for the case where there are no entries. |
4382 | * In this case, "ma1" cannot be greater than "ma2", |
4383 | * but it is (greater than or) equal to "ma2". |
4384 | */ |
4385 | static __isl_give isl_setisl_map *isl_multi_aff_lex_gte_set_0d( |
4386 | __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2, int equal) |
4387 | { |
4388 | isl_space *space; |
4389 | |
4390 | space = isl_multi_aff_get_domain_space(ma1); |
4391 | |
4392 | isl_multi_aff_free(ma1); |
4393 | isl_multi_aff_free(ma2); |
4394 | |
4395 | if (equal) |
4396 | return isl_set_universe(space); |
4397 | else |
4398 | return isl_set_empty(space); |
4399 | } |
4400 | |
4401 | /* Return the set where entry "i" of "ma1" and "ma2" |
4402 | * satisfy the relation prescribed by "cmp". |
4403 | */ |
4404 | static __isl_give isl_setisl_map *isl_multi_aff_order_at(__isl_keep isl_multi_aff *ma1, |
4405 | __isl_keep isl_multi_aff *ma2, int i, |
4406 | __isl_give isl_setisl_map *(*cmp)(__isl_take isl_aff *aff1, |
4407 | __isl_take isl_aff *aff2)) |
4408 | { |
4409 | isl_aff *aff1, *aff2; |
4410 | |
4411 | aff1 = isl_multi_aff_get_at(ma1, i); |
4412 | aff2 = isl_multi_aff_get_at(ma2, i); |
4413 | return cmp(aff1, aff2); |
4414 | } |
4415 | |
4416 | /* Return the set of domain elements where "ma1" is lexicographically |
4417 | * greater than to "ma2". If "equal" is set, then include the domain |
4418 | * elements where they are equal. |
4419 | * |
4420 | * In particular, for all but the final entry, |
4421 | * include the set of elements where this entry is strictly greater in "ma1" |
4422 | * and all previous entries are equal. |
4423 | * The final entry is also allowed to be equal in the two functions |
4424 | * if "equal" is set. |
4425 | * |
4426 | * The case where there are no entries is handled separately. |
4427 | */ |
4428 | static __isl_give isl_setisl_map *isl_multi_aff_lex_gte_set( |
4429 | __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2, int equal) |
4430 | { |
4431 | int i; |
4432 | isl_size n; |
4433 | isl_space *space; |
4434 | isl_setisl_map *res; |
4435 | isl_setisl_map *equal_set; |
4436 | isl_setisl_map *gte; |
4437 | |
4438 | if (isl_multi_aff_check_equal_space(ma1, ma2) < 0) |
4439 | goto error; |
4440 | n = isl_multi_aff_size(ma1); |
4441 | if (n < 0) |
4442 | goto error; |
4443 | if (n == 0) |
4444 | return isl_multi_aff_lex_gte_set_0d(ma1, ma2, equal); |
4445 | |
4446 | space = isl_multi_aff_get_domain_space(ma1); |
4447 | res = isl_set_empty(isl_space_copy(space)); |
4448 | equal_set = isl_set_universe(space); |
4449 | |
4450 | for (i = 0; i + 1 < n; ++i) { |
4451 | isl_bool empty; |
4452 | isl_setisl_map *gt, *eq; |
4453 | |
4454 | gt = isl_multi_aff_order_at(ma1, ma2, i, &isl_aff_gt_set); |
4455 | gt = isl_set_intersect(gt, isl_set_copy(equal_set)); |
4456 | res = isl_set_union(res, gt); |
4457 | eq = isl_multi_aff_order_at(ma1, ma2, i, &isl_aff_eq_set); |
4458 | equal_set = isl_set_intersect(equal_set, eq); |
4459 | |
4460 | empty = isl_set_is_empty(equal_set); |
4461 | if (empty >= 0 && empty) |
4462 | break; |
4463 | } |
4464 | |
4465 | if (equal) |
4466 | gte = isl_multi_aff_order_at(ma1, ma2, n - 1, &isl_aff_ge_set); |
4467 | else |
4468 | gte = isl_multi_aff_order_at(ma1, ma2, n - 1, &isl_aff_gt_set); |
4469 | isl_multi_aff_free(ma1); |
4470 | isl_multi_aff_free(ma2); |
4471 | |
4472 | gte = isl_set_intersect(gte, equal_set); |
4473 | return isl_set_union(res, gte); |
4474 | error: |
4475 | isl_multi_aff_free(ma1); |
4476 | isl_multi_aff_free(ma2); |
4477 | return NULL((void*)0); |
4478 | } |
4479 | |
4480 | /* Return the set of domain elements where "ma1" is lexicographically |
4481 | * greater than or equal to "ma2". |
4482 | */ |
4483 | __isl_give isl_setisl_map *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1, |
4484 | __isl_take isl_multi_aff *ma2) |
4485 | { |
4486 | return isl_multi_aff_lex_gte_set(ma1, ma2, 1); |
4487 | } |
4488 | |
4489 | /* Return the set of domain elements where "ma1" is lexicographically |
4490 | * greater than "ma2". |
4491 | */ |
4492 | __isl_give isl_setisl_map *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1, |
4493 | __isl_take isl_multi_aff *ma2) |
4494 | { |
4495 | return isl_multi_aff_lex_gte_set(ma1, ma2, 0); |
4496 | } |
4497 | |
4498 | #define isl_multi_aff_zero_in_spaceisl_multi_aff_zero isl_multi_aff_zero |
4499 | |
4500 | #undef PWisl_pw_union_pw_aff |
4501 | #define PWisl_pw_union_pw_aff isl_pw_multi_aff |
4502 | #undef BASEunion_pw_aff |
4503 | #define BASEunion_pw_aff multi_aff |
4504 | #undef EL_IS_ZEROis_empty |
4505 | #define EL_IS_ZEROis_empty is_empty |
4506 | #undef ZEROempty |
4507 | #define ZEROempty empty |
4508 | #undef IS_ZEROis_empty |
4509 | #define IS_ZEROis_empty is_empty |
4510 | #undef FIELDmaff |
4511 | #define FIELDmaff maff |
4512 | #undef DEFAULT_IS_ZERO0 |
4513 | #define DEFAULT_IS_ZERO0 0 |
4514 | |
4515 | #include <isl_pw_templ.c> |
4516 | #include <isl_pw_add_constant_multi_val_templ.c> |
4517 | #include <isl_pw_add_constant_val_templ.c> |
4518 | #include <isl_pw_bind_domain_templ.c> |
4519 | #include <isl_pw_insert_dims_templ.c> |
4520 | #include <isl_pw_insert_domain_templ.c> |
4521 | #include <isl_pw_locals_templ.c> |
4522 | #include <isl_pw_move_dims_templ.c> |
4523 | #include <isl_pw_neg_templ.c> |
4524 | #include <isl_pw_pullback_templ.c> |
4525 | #include <isl_pw_range_tuple_id_templ.c> |
4526 | #include <isl_pw_union_opt.c> |
4527 | |
4528 | #undef BASEunion_pw_aff |
4529 | #define BASEunion_pw_aff pw_multi_aff |
4530 | |
4531 | #include <isl_union_multi.c> |
4532 | #include "isl_union_locals_templ.c" |
4533 | #include <isl_union_neg.c> |
4534 | |
4535 | #undef BASEunion_pw_aff |
4536 | #define BASEunion_pw_aff multi_aff |
4537 | |
4538 | #include <isl_union_pw_templ.c> |
4539 | |
4540 | /* Generic function for extracting a factor from a product "pma". |
4541 | * "check_space" checks that the space is that of the right kind of product. |
4542 | * "space_factor" extracts the factor from the space. |
4543 | * "multi_aff_factor" extracts the factor from the constituent functions. |
4544 | */ |
4545 | static __isl_give isl_pw_multi_aff *pw_multi_aff_factor( |
4546 | __isl_take isl_pw_multi_aff *pma, |
4547 | isl_stat (*check_space)(__isl_keep isl_pw_multi_aff *pma), |
4548 | __isl_give isl_space *(*space_factor)(__isl_take isl_space *space), |
4549 | __isl_give isl_multi_aff *(*multi_aff_factor)( |
4550 | __isl_take isl_multi_aff *ma)) |
4551 | { |
4552 | int i; |
4553 | isl_space *space; |
4554 | |
4555 | if (check_space(pma) < 0) |
4556 | return isl_pw_multi_aff_free(pma); |
4557 | |
4558 | space = isl_pw_multi_aff_take_space(pma); |
4559 | space = space_factor(space); |
4560 | |
4561 | for (i = 0; pma && i < pma->n; ++i) { |
4562 | isl_multi_aff *ma; |
4563 | |
4564 | ma = isl_pw_multi_aff_take_base_at(pma, i); |
4565 | ma = multi_aff_factor(ma); |
4566 | pma = isl_pw_multi_aff_restore_base_at(pma, i, ma); |
4567 | } |
4568 | |
4569 | pma = isl_pw_multi_aff_restore_space(pma, space); |
4570 | |
4571 | return pma; |
4572 | } |
4573 | |
4574 | /* Is the range of "pma" a wrapped relation? |
4575 | */ |
4576 | static isl_bool isl_pw_multi_aff_range_is_wrapping( |
4577 | __isl_keep isl_pw_multi_aff *pma) |
4578 | { |
4579 | return isl_space_range_is_wrapping(isl_pw_multi_aff_peek_space(pma)); |
4580 | } |
4581 | |
4582 | /* Check that the range of "pma" is a product. |
4583 | */ |
4584 | static isl_stat pw_multi_aff_check_range_product( |
4585 | __isl_keep isl_pw_multi_aff *pma) |
4586 | { |
4587 | isl_bool wraps; |
4588 | |
4589 | wraps = isl_pw_multi_aff_range_is_wrapping(pma); |
4590 | if (wraps < 0) |
4591 | return isl_stat_error; |
4592 | if (!wraps) |
4593 | isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,do { isl_handle_error(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid , "range is not a product", "polly/lib/External/isl/isl_aff.c" , 4594); return isl_stat_error; } while (0) |
4594 | "range is not a product", return isl_stat_error)do { isl_handle_error(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid , "range is not a product", "polly/lib/External/isl/isl_aff.c" , 4594); return isl_stat_error; } while (0); |
4595 | return isl_stat_ok; |
4596 | } |
4597 | |
4598 | /* Given a function A -> [B -> C], extract the function A -> B. |
4599 | */ |
4600 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_domain( |
4601 | __isl_take isl_pw_multi_aff *pma) |
4602 | { |
4603 | return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product, |
4604 | &isl_space_range_factor_domain, |
4605 | &isl_multi_aff_range_factor_domain); |
4606 | } |
4607 | |
4608 | /* Given a function A -> [B -> C], extract the function A -> C. |
4609 | */ |
4610 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_range( |
4611 | __isl_take isl_pw_multi_aff *pma) |
4612 | { |
4613 | return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product, |
4614 | &isl_space_range_factor_range, |
4615 | &isl_multi_aff_range_factor_range); |
4616 | } |
4617 | |
4618 | /* Given two piecewise multi affine expressions, return a piecewise |
4619 | * multi-affine expression defined on the union of the definition domains |
4620 | * of the inputs that is equal to the lexicographic maximum of the two |
4621 | * inputs on each cell. If only one of the two inputs is defined on |
4622 | * a given cell, then it is considered to be the maximum. |
4623 | */ |
4624 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax( |
4625 | __isl_take isl_pw_multi_aff *pma1, |
4626 | __isl_take isl_pw_multi_aff *pma2) |
4627 | { |
4628 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
4629 | return isl_pw_multi_aff_union_opt_cmp(pma1, pma2, |
4630 | &isl_multi_aff_lex_ge_set); |
4631 | } |
4632 | |
4633 | /* Given two piecewise multi affine expressions, return a piecewise |
4634 | * multi-affine expression defined on the union of the definition domains |
4635 | * of the inputs that is equal to the lexicographic minimum of the two |
4636 | * inputs on each cell. If only one of the two inputs is defined on |
4637 | * a given cell, then it is considered to be the minimum. |
4638 | */ |
4639 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin( |
4640 | __isl_take isl_pw_multi_aff *pma1, |
4641 | __isl_take isl_pw_multi_aff *pma2) |
4642 | { |
4643 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
4644 | return isl_pw_multi_aff_union_opt_cmp(pma1, pma2, |
4645 | &isl_multi_aff_lex_le_set); |
4646 | } |
4647 | |
4648 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_add( |
4649 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
4650 | { |
4651 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
4652 | return isl_pw_multi_aff_on_shared_domain(pma1, pma2, |
4653 | &isl_multi_aff_add); |
4654 | } |
4655 | |
4656 | /* Subtract "pma2" from "pma1" and return the result. |
4657 | */ |
4658 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub( |
4659 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
4660 | { |
4661 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
4662 | return isl_pw_multi_aff_on_shared_domain(pma1, pma2, |
4663 | &isl_multi_aff_sub); |
4664 | } |
4665 | |
4666 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add( |
4667 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
4668 | { |
4669 | return isl_pw_multi_aff_union_add_(pma1, pma2); |
4670 | } |
4671 | |
4672 | /* Compute the sum of "upa1" and "upa2" on the union of their domains, |
4673 | * with the actual sum on the shared domain and |
4674 | * the defined expression on the symmetric difference of the domains. |
4675 | */ |
4676 | __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add( |
4677 | __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2) |
4678 | { |
4679 | return isl_union_pw_aff_union_add_(upa1, upa2); |
4680 | } |
4681 | |
4682 | /* Compute the sum of "upma1" and "upma2" on the union of their domains, |
4683 | * with the actual sum on the shared domain and |
4684 | * the defined expression on the symmetric difference of the domains. |
4685 | */ |
4686 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add( |
4687 | __isl_take isl_union_pw_multi_aff *upma1, |
4688 | __isl_take isl_union_pw_multi_aff *upma2) |
4689 | { |
4690 | return isl_union_pw_multi_aff_union_add_(upma1, upma2); |
4691 | } |
4692 | |
4693 | /* Given two piecewise multi-affine expressions A -> B and C -> D, |
4694 | * construct a piecewise multi-affine expression [A -> C] -> [B -> D]. |
4695 | */ |
4696 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_product( |
4697 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
4698 | { |
4699 | int i, j, n; |
4700 | isl_space *space; |
4701 | isl_pw_multi_aff *res; |
4702 | |
4703 | if (isl_pw_multi_aff_align_params_bin(&pma1, &pma2) < 0) |
4704 | goto error; |
4705 | |
4706 | n = pma1->n * pma2->n; |
4707 | space = isl_space_product(isl_space_copy(pma1->dim), |
4708 | isl_space_copy(pma2->dim)); |
4709 | res = isl_pw_multi_aff_alloc_size(space, n); |
4710 | |
4711 | for (i = 0; i < pma1->n; ++i) { |
4712 | for (j = 0; j < pma2->n; ++j) { |
4713 | isl_setisl_map *domain; |
4714 | isl_multi_aff *ma; |
4715 | |
4716 | domain = isl_set_product(isl_set_copy(pma1->p[i].set), |
4717 | isl_set_copy(pma2->p[j].set)); |
4718 | ma = isl_multi_aff_product( |
4719 | isl_multi_aff_copy(pma1->p[i].maff), |
4720 | isl_multi_aff_copy(pma2->p[j].maff)); |
4721 | res = isl_pw_multi_aff_add_piece(res, domain, ma); |
4722 | } |
4723 | } |
4724 | |
4725 | isl_pw_multi_aff_free(pma1); |
4726 | isl_pw_multi_aff_free(pma2); |
4727 | return res; |
4728 | error: |
4729 | isl_pw_multi_aff_free(pma1); |
4730 | isl_pw_multi_aff_free(pma2); |
4731 | return NULL((void*)0); |
4732 | } |
4733 | |
4734 | /* Subtract the initial "n" elements in "ma" with coefficients in "c" and |
4735 | * denominator "denom". |
4736 | * "denom" is allowed to be negative, in which case the actual denominator |
4737 | * is -denom and the expressions are added instead. |
4738 | */ |
4739 | static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff, |
4740 | __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom) |
4741 | { |
4742 | int i, first; |
4743 | int sign; |
4744 | isl_int d; |
4745 | |
4746 | first = isl_seq_first_non_zero(c, n); |
4747 | if (first == -1) |
4748 | return aff; |
4749 | |
4750 | sign = isl_int_sgn(denom)isl_sioimath_sgn(*(denom)); |
4751 | isl_int_init(d)isl_sioimath_init((d)); |
4752 | isl_int_abs(d, denom)isl_sioimath_abs((d), *(denom)); |
4753 | for (i = first; i < n; ++i) { |
4754 | isl_aff *aff_i; |
4755 | |
4756 | if (isl_int_is_zero(c[i])(isl_sioimath_sgn(*(c[i])) == 0)) |
4757 | continue; |
4758 | aff_i = isl_multi_aff_get_aff(ma, i); |
4759 | aff_i = isl_aff_scale(aff_i, c[i]); |
4760 | aff_i = isl_aff_scale_down(aff_i, d); |
4761 | if (sign >= 0) |
4762 | aff = isl_aff_sub(aff, aff_i); |
4763 | else |
4764 | aff = isl_aff_add(aff, aff_i); |
4765 | } |
4766 | isl_int_clear(d)isl_sioimath_clear((d)); |
4767 | |
4768 | return aff; |
4769 | } |
4770 | |
4771 | /* Extract an affine expression that expresses the output dimension "pos" |
4772 | * of "bmap" in terms of the parameters and input dimensions from |
4773 | * equality "eq". |
4774 | * Note that this expression may involve integer divisions defined |
4775 | * in terms of parameters and input dimensions. |
4776 | * The equality may also involve references to earlier (but not later) |
4777 | * output dimensions. These are replaced by the corresponding elements |
4778 | * in "ma". |
4779 | * |
4780 | * If the equality is of the form |
4781 | * |
4782 | * f(i) + h(j) + a x + g(i) = 0, |
4783 | * |
4784 | * with f(i) a linear combinations of the parameters and input dimensions, |
4785 | * g(i) a linear combination of integer divisions defined in terms of the same |
4786 | * and h(j) a linear combinations of earlier output dimensions, |
4787 | * then the affine expression is |
4788 | * |
4789 | * (-f(i) - g(i))/a - h(j)/a |
4790 | * |
4791 | * If the equality is of the form |
4792 | * |
4793 | * f(i) + h(j) - a x + g(i) = 0, |
4794 | * |
4795 | * then the affine expression is |
4796 | * |
4797 | * (f(i) + g(i))/a - h(j)/(-a) |
4798 | * |
4799 | * |
4800 | * If "div" refers to an integer division (i.e., it is smaller than |
4801 | * the number of integer divisions), then the equality constraint |
4802 | * does involve an integer division (the one at position "div") that |
4803 | * is defined in terms of output dimensions. However, this integer |
4804 | * division can be eliminated by exploiting a pair of constraints |
4805 | * x >= l and x <= l + n, with n smaller than the coefficient of "div" |
4806 | * in the equality constraint. "ineq" refers to inequality x >= l, i.e., |
4807 | * -l + x >= 0. |
4808 | * In particular, let |
4809 | * |
4810 | * x = e(i) + m floor(...) |
4811 | * |
4812 | * with e(i) the expression derived above and floor(...) the integer |
4813 | * division involving output dimensions. |
4814 | * From |
4815 | * |
4816 | * l <= x <= l + n, |
4817 | * |
4818 | * we have |
4819 | * |
4820 | * 0 <= x - l <= n |
4821 | * |
4822 | * This means |
4823 | * |
4824 | * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m |
4825 | * = (e(i) - l) mod m |
4826 | * |
4827 | * Therefore, |
4828 | * |
4829 | * x - l = (e(i) - l) mod m |
4830 | * |
4831 | * or |
4832 | * |
4833 | * x = ((e(i) - l) mod m) + l |
4834 | * |
4835 | * The variable "shift" below contains the expression -l, which may |
4836 | * also involve a linear combination of earlier output dimensions. |
4837 | */ |
4838 | static __isl_give isl_aff *extract_aff_from_equality( |
4839 | __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq, |
4840 | __isl_keep isl_multi_aff *ma) |
4841 | { |
4842 | unsigned o_out; |
4843 | isl_size n_div, n_out; |
4844 | isl_ctx *ctx; |
4845 | isl_local_space *ls; |
4846 | isl_aff *aff, *shift; |
4847 | isl_val *mod; |
4848 | |
4849 | ctx = isl_basic_map_get_ctx(bmap); |
4850 | ls = isl_basic_map_get_local_space(bmap); |
4851 | ls = isl_local_space_domain(ls); |
4852 | aff = isl_aff_alloc(isl_local_space_copy(ls)); |
4853 | if (!aff) |
4854 | goto error; |
4855 | o_out = isl_basic_map_offset(bmap, isl_dim_out); |
4856 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
4857 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4858 | if (n_out < 0 || n_div < 0) |
4859 | goto error; |
4860 | if (isl_int_is_neg(bmap->eq[eq][o_out + pos])(isl_sioimath_sgn(*(bmap->eq[eq][o_out + pos])) < 0)) { |
4861 | isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out); |
4862 | isl_seq_cpy(aff->v->el + 1 + o_out, |
4863 | bmap->eq[eq] + o_out + n_out, n_div); |
4864 | } else { |
4865 | isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out); |
4866 | isl_seq_neg(aff->v->el + 1 + o_out, |
4867 | bmap->eq[eq] + o_out + n_out, n_div); |
4868 | } |
4869 | if (div < n_div) |
4870 | isl_int_set_si(aff->v->el[1 + o_out + div], 0)isl_sioimath_set_si((aff->v->el[1 + o_out + div]), 0); |
4871 | isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos])isl_sioimath_abs((aff->v->el[0]), *(bmap->eq[eq][o_out + pos])); |
4872 | aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out, |
4873 | bmap->eq[eq][o_out + pos]); |
4874 | if (div < n_div) { |
4875 | shift = isl_aff_alloc(isl_local_space_copy(ls)); |
4876 | if (!shift) |
4877 | goto error; |
4878 | isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out); |
4879 | isl_seq_cpy(shift->v->el + 1 + o_out, |
4880 | bmap->ineq[ineq] + o_out + n_out, n_div); |
4881 | isl_int_set_si(shift->v->el[0], 1)isl_sioimath_set_si((shift->v->el[0]), 1); |
4882 | shift = subtract_initial(shift, ma, pos, |
4883 | bmap->ineq[ineq] + o_out, ctx->negone); |
4884 | aff = isl_aff_add(aff, isl_aff_copy(shift)); |
4885 | mod = isl_val_int_from_isl_int(ctx, |
4886 | bmap->eq[eq][o_out + n_out + div]); |
4887 | mod = isl_val_abs(mod); |
4888 | aff = isl_aff_mod_val(aff, mod); |
4889 | aff = isl_aff_sub(aff, shift); |
4890 | } |
4891 | |
4892 | isl_local_space_free(ls); |
4893 | return aff; |
4894 | error: |
4895 | isl_local_space_free(ls); |
4896 | isl_aff_free(aff); |
4897 | return NULL((void*)0); |
4898 | } |
4899 | |
4900 | /* Given a basic map with output dimensions defined |
4901 | * in terms of the parameters input dimensions and earlier |
4902 | * output dimensions using an equality (and possibly a pair on inequalities), |
4903 | * extract an isl_aff that expresses output dimension "pos" in terms |
4904 | * of the parameters and input dimensions. |
4905 | * Note that this expression may involve integer divisions defined |
4906 | * in terms of parameters and input dimensions. |
4907 | * "ma" contains the expressions corresponding to earlier output dimensions. |
4908 | * |
4909 | * This function shares some similarities with |
4910 | * isl_basic_map_has_defining_equality and isl_constraint_get_bound. |
4911 | */ |
4912 | static __isl_give isl_aff *extract_isl_aff_from_basic_map( |
4913 | __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma) |
4914 | { |
4915 | int eq, div, ineq; |
4916 | isl_aff *aff; |
4917 | |
4918 | if (!bmap) |
4919 | return NULL((void*)0); |
4920 | eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq); |
4921 | if (eq >= bmap->n_eq) |
4922 | isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_invalid , "unable to find suitable equality", "polly/lib/External/isl/isl_aff.c" , 4923); return ((void*)0); } while (0) |
4923 | "unable to find suitable equality", return NULL)do { isl_handle_error(isl_basic_map_get_ctx(bmap), isl_error_invalid , "unable to find suitable equality", "polly/lib/External/isl/isl_aff.c" , 4923); return ((void*)0); } while (0); |
4924 | aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma); |
4925 | |
4926 | aff = isl_aff_remove_unused_divs(aff); |
4927 | return aff; |
4928 | } |
4929 | |
4930 | /* Given a basic map where each output dimension is defined |
4931 | * in terms of the parameters and input dimensions using an equality, |
4932 | * extract an isl_multi_aff that expresses the output dimensions in terms |
4933 | * of the parameters and input dimensions. |
4934 | */ |
4935 | static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map( |
4936 | __isl_take isl_basic_map *bmap) |
4937 | { |
4938 | int i; |
4939 | isl_size n_out; |
4940 | isl_multi_aff *ma; |
4941 | |
4942 | if (!bmap) |
4943 | return NULL((void*)0); |
4944 | |
4945 | ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap)); |
4946 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
4947 | if (n_out < 0) |
4948 | ma = isl_multi_aff_free(ma); |
4949 | |
4950 | for (i = 0; i < n_out; ++i) { |
4951 | isl_aff *aff; |
4952 | |
4953 | aff = extract_isl_aff_from_basic_map(bmap, i, ma); |
4954 | ma = isl_multi_aff_set_aff(ma, i, aff); |
4955 | } |
4956 | |
4957 | isl_basic_map_free(bmap); |
4958 | |
4959 | return ma; |
4960 | } |
4961 | |
4962 | /* Given a basic set where each set dimension is defined |
4963 | * in terms of the parameters using an equality, |
4964 | * extract an isl_multi_aff that expresses the set dimensions in terms |
4965 | * of the parameters. |
4966 | */ |
4967 | __isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities( |
4968 | __isl_take isl_basic_setisl_basic_map *bset) |
4969 | { |
4970 | return extract_isl_multi_aff_from_basic_map(bset); |
4971 | } |
4972 | |
4973 | /* Create an isl_pw_multi_aff that is equivalent to |
4974 | * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain). |
4975 | * The given basic map is such that each output dimension is defined |
4976 | * in terms of the parameters and input dimensions using an equality. |
4977 | * |
4978 | * Since some applications expect the result of isl_pw_multi_aff_from_map |
4979 | * to only contain integer affine expressions, we compute the floor |
4980 | * of the expression before returning. |
4981 | * |
4982 | * Remove all constraints involving local variables without |
4983 | * an explicit representation (resulting in the removal of those |
4984 | * local variables) prior to the actual extraction to ensure |
4985 | * that the local spaces in which the resulting affine expressions |
4986 | * are created do not contain any unknown local variables. |
4987 | * Removing such constraints is safe because constraints involving |
4988 | * unknown local variables are not used to determine whether |
4989 | * a basic map is obviously single-valued. |
4990 | */ |
4991 | static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map( |
4992 | __isl_take isl_setisl_map *domain, __isl_take isl_basic_map *bmap) |
4993 | { |
4994 | isl_multi_aff *ma; |
4995 | |
4996 | bmap = isl_basic_map_drop_constraints_involving_unknown_divs(bmap); |
4997 | ma = extract_isl_multi_aff_from_basic_map(bmap); |
4998 | ma = isl_multi_aff_floor(ma); |
4999 | return isl_pw_multi_aff_alloc(domain, ma); |
5000 | } |
5001 | |
5002 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. |
5003 | * This obviously only works if the input "map" is single-valued. |
5004 | * If so, we compute the lexicographic minimum of the image in the form |
5005 | * of an isl_pw_multi_aff. Since the image is unique, it is equal |
5006 | * to its lexicographic minimum. |
5007 | * If the input is not single-valued, we produce an error. |
5008 | */ |
5009 | static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base( |
5010 | __isl_take isl_map *map) |
5011 | { |
5012 | int i; |
5013 | int sv; |
5014 | isl_pw_multi_aff *pma; |
5015 | |
5016 | sv = isl_map_is_single_valued(map); |
5017 | if (sv < 0) |
5018 | goto error; |
5019 | if (!sv) |
5020 | isl_die(isl_map_get_ctx(map), isl_error_invalid,do { isl_handle_error(isl_map_get_ctx(map), isl_error_invalid , "map is not single-valued", "polly/lib/External/isl/isl_aff.c" , 5021); goto error; } while (0) |
5021 | "map is not single-valued", goto error)do { isl_handle_error(isl_map_get_ctx(map), isl_error_invalid , "map is not single-valued", "polly/lib/External/isl/isl_aff.c" , 5021); goto error; } while (0); |
5022 | map = isl_map_make_disjoint(map); |
5023 | if (!map) |
5024 | return NULL((void*)0); |
5025 | |
5026 | pma = isl_pw_multi_aff_empty(isl_map_get_space(map)); |
5027 | |
5028 | for (i = 0; i < map->n; ++i) { |
5029 | isl_pw_multi_aff *pma_i; |
5030 | isl_basic_map *bmap; |
5031 | bmap = isl_basic_map_copy(map->p[i]); |
5032 | pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap); |
5033 | pma = isl_pw_multi_aff_add_disjoint(pma, pma_i); |
5034 | } |
5035 | |
5036 | isl_map_free(map); |
5037 | return pma; |
5038 | error: |
5039 | isl_map_free(map); |
5040 | return NULL((void*)0); |
5041 | } |
5042 | |
5043 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map, |
5044 | * taking into account that the output dimension at position "d" |
5045 | * can be represented as |
5046 | * |
5047 | * x = floor((e(...) + c1) / m) |
5048 | * |
5049 | * given that constraint "i" is of the form |
5050 | * |
5051 | * e(...) + c1 - m x >= 0 |
5052 | * |
5053 | * |
5054 | * Let "map" be of the form |
5055 | * |
5056 | * A -> B |
5057 | * |
5058 | * We construct a mapping |
5059 | * |
5060 | * A -> [A -> x = floor(...)] |
5061 | * |
5062 | * apply that to the map, obtaining |
5063 | * |
5064 | * [A -> x = floor(...)] -> B |
5065 | * |
5066 | * and equate dimension "d" to x. |
5067 | * We then compute a isl_pw_multi_aff representation of the resulting map |
5068 | * and plug in the mapping above. |
5069 | */ |
5070 | static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div( |
5071 | __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i) |
5072 | { |
5073 | isl_ctx *ctx; |
5074 | isl_space *space = NULL((void*)0); |
5075 | isl_local_space *ls; |
5076 | isl_multi_aff *ma; |
5077 | isl_aff *aff; |
5078 | isl_vec *v; |
5079 | isl_map *insert; |
5080 | int offset; |
5081 | isl_size n; |
5082 | isl_size n_in; |
5083 | isl_pw_multi_aff *pma; |
5084 | isl_bool is_set; |
5085 | |
5086 | is_set = isl_map_is_set(map); |
5087 | if (is_set < 0) |
5088 | goto error; |
5089 | |
5090 | offset = isl_basic_map_offset(hull, isl_dim_out); |
5091 | ctx = isl_map_get_ctx(map); |
5092 | space = isl_space_domain(isl_map_get_space(map)); |
5093 | n_in = isl_space_dim(space, isl_dim_set); |
5094 | n = isl_space_dim(space, isl_dim_all); |
5095 | if (n_in < 0 || n < 0) |
5096 | goto error; |
5097 | |
5098 | v = isl_vec_alloc(ctx, 1 + 1 + n); |
5099 | if (v) { |
5100 | isl_int_neg(v->el[0], hull->ineq[i][offset + d])isl_sioimath_neg((v->el[0]), *(hull->ineq[i][offset + d ])); |
5101 | isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n); |
5102 | } |
5103 | isl_basic_map_free(hull); |
5104 | |
5105 | ls = isl_local_space_from_space(isl_space_copy(space)); |
5106 | aff = isl_aff_alloc_vec(ls, v); |
5107 | aff = isl_aff_floor(aff); |
5108 | if (is_set) { |
5109 | isl_space_free(space); |
5110 | ma = isl_multi_aff_from_aff(aff); |
5111 | } else { |
5112 | ma = isl_multi_aff_identity(isl_space_map_from_set(space)); |
5113 | ma = isl_multi_aff_range_product(ma, |
5114 | isl_multi_aff_from_aff(aff)); |
5115 | } |
5116 | |
5117 | insert = isl_map_from_multi_aff_internal(isl_multi_aff_copy(ma)); |
5118 | map = isl_map_apply_domain(map, insert); |
5119 | map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d); |
5120 | pma = isl_pw_multi_aff_from_map(map); |
5121 | pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma); |
5122 | |
5123 | return pma; |
5124 | error: |
5125 | isl_space_free(space); |
5126 | isl_map_free(map); |
5127 | isl_basic_map_free(hull); |
5128 | return NULL((void*)0); |
5129 | } |
5130 | |
5131 | /* Is constraint "c" of the form |
5132 | * |
5133 | * e(...) + c1 - m x >= 0 |
5134 | * |
5135 | * or |
5136 | * |
5137 | * -e(...) + c2 + m x >= 0 |
5138 | * |
5139 | * where m > 1 and e only depends on parameters and input dimensions? |
5140 | * |
5141 | * "offset" is the offset of the output dimensions |
5142 | * "pos" is the position of output dimension x. |
5143 | */ |
5144 | static int is_potential_div_constraint(isl_int *c, int offset, int d, int total) |
5145 | { |
5146 | if (isl_int_is_zero(c[offset + d])(isl_sioimath_sgn(*(c[offset + d])) == 0)) |
5147 | return 0; |
5148 | if (isl_int_is_one(c[offset + d])(isl_sioimath_cmp_si(*(c[offset + d]), 1) == 0)) |
5149 | return 0; |
5150 | if (isl_int_is_negone(c[offset + d])(isl_sioimath_cmp_si(*(c[offset + d]), -1) == 0)) |
5151 | return 0; |
5152 | if (isl_seq_first_non_zero(c + offset, d) != -1) |
5153 | return 0; |
5154 | if (isl_seq_first_non_zero(c + offset + d + 1, |
5155 | total - (offset + d + 1)) != -1) |
5156 | return 0; |
5157 | return 1; |
5158 | } |
5159 | |
5160 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. |
5161 | * |
5162 | * As a special case, we first check if there is any pair of constraints, |
5163 | * shared by all the basic maps in "map" that force a given dimension |
5164 | * to be equal to the floor of some affine combination of the input dimensions. |
5165 | * |
5166 | * In particular, if we can find two constraints |
5167 | * |
5168 | * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1 |
5169 | * |
5170 | * and |
5171 | * |
5172 | * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2 |
5173 | * |
5174 | * where m > 1 and e only depends on parameters and input dimensions, |
5175 | * and such that |
5176 | * |
5177 | * c1 + c2 < m i.e., -c2 >= c1 - (m - 1) |
5178 | * |
5179 | * then we know that we can take |
5180 | * |
5181 | * x = floor((e(...) + c1) / m) |
5182 | * |
5183 | * without having to perform any computation. |
5184 | * |
5185 | * Note that we know that |
5186 | * |
5187 | * c1 + c2 >= 1 |
5188 | * |
5189 | * If c1 + c2 were 0, then we would have detected an equality during |
5190 | * simplification. If c1 + c2 were negative, then we would have detected |
5191 | * a contradiction. |
5192 | */ |
5193 | static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div( |
5194 | __isl_take isl_map *map) |
5195 | { |
5196 | int d; |
5197 | isl_size dim; |
5198 | int i, j, n; |
5199 | int offset; |
5200 | isl_size total; |
5201 | isl_int sum; |
5202 | isl_basic_map *hull; |
5203 | |
5204 | hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); |
5205 | dim = isl_map_dim(map, isl_dim_out); |
5206 | total = isl_basic_map_dim(hull, isl_dim_all); |
5207 | if (dim < 0 || total < 0) |
5208 | goto error; |
5209 | |
5210 | isl_int_init(sum)isl_sioimath_init((sum)); |
5211 | offset = isl_basic_map_offset(hull, isl_dim_out); |
5212 | n = hull->n_ineq; |
5213 | for (d = 0; d < dim; ++d) { |
5214 | for (i = 0; i < n; ++i) { |
5215 | if (!is_potential_div_constraint(hull->ineq[i], |
5216 | offset, d, 1 + total)) |
5217 | continue; |
5218 | for (j = i + 1; j < n; ++j) { |
5219 | if (!isl_seq_is_neg(hull->ineq[i] + 1, |
5220 | hull->ineq[j] + 1, total)) |
5221 | continue; |
5222 | isl_int_add(sum, hull->ineq[i][0],isl_sioimath_add((sum), *(hull->ineq[i][0]), *(hull->ineq [j][0])) |
5223 | hull->ineq[j][0])isl_sioimath_add((sum), *(hull->ineq[i][0]), *(hull->ineq [j][0])); |
5224 | if (isl_int_abs_lt(sum,(isl_sioimath_abs_cmp(*(sum), *(hull->ineq[i][offset + d]) ) < 0) |
5225 | hull->ineq[i][offset + d])(isl_sioimath_abs_cmp(*(sum), *(hull->ineq[i][offset + d]) ) < 0)) |
5226 | break; |
5227 | |
5228 | } |
5229 | if (j >= n) |
5230 | continue; |
5231 | isl_int_clear(sum)isl_sioimath_clear((sum)); |
5232 | if (isl_int_is_pos(hull->ineq[j][offset + d])(isl_sioimath_sgn(*(hull->ineq[j][offset + d])) > 0)) |
5233 | j = i; |
5234 | return pw_multi_aff_from_map_div(map, hull, d, j); |
5235 | } |
5236 | } |
5237 | isl_int_clear(sum)isl_sioimath_clear((sum)); |
5238 | isl_basic_map_free(hull); |
5239 | return pw_multi_aff_from_map_base(map); |
5240 | error: |
5241 | isl_map_free(map); |
5242 | isl_basic_map_free(hull); |
5243 | return NULL((void*)0); |
5244 | } |
5245 | |
5246 | /* Given an affine expression |
5247 | * |
5248 | * [A -> B] -> f(A,B) |
5249 | * |
5250 | * construct an isl_multi_aff |
5251 | * |
5252 | * [A -> B] -> B' |
5253 | * |
5254 | * such that dimension "d" in B' is set to "aff" and the remaining |
5255 | * dimensions are set equal to the corresponding dimensions in B. |
5256 | * "n_in" is the dimension of the space A. |
5257 | * "n_out" is the dimension of the space B. |
5258 | * |
5259 | * If "is_set" is set, then the affine expression is of the form |
5260 | * |
5261 | * [B] -> f(B) |
5262 | * |
5263 | * and we construct an isl_multi_aff |
5264 | * |
5265 | * B -> B' |
5266 | */ |
5267 | static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d, |
5268 | unsigned n_in, unsigned n_out, int is_set) |
5269 | { |
5270 | int i; |
5271 | isl_multi_aff *ma; |
5272 | isl_space *space, *space2; |
5273 | isl_local_space *ls; |
5274 | |
5275 | space = isl_aff_get_domain_space(aff); |
5276 | ls = isl_local_space_from_space(isl_space_copy(space)); |
5277 | space2 = isl_space_copy(space); |
5278 | if (!is_set) |
5279 | space2 = isl_space_range(isl_space_unwrap(space2)); |
5280 | space = isl_space_map_from_domain_and_range(space, space2); |
5281 | ma = isl_multi_aff_alloc(space); |
5282 | ma = isl_multi_aff_set_aff(ma, d, aff); |
5283 | |
5284 | for (i = 0; i < n_out; ++i) { |
5285 | if (i == d) |
5286 | continue; |
5287 | aff = isl_aff_var_on_domain(isl_local_space_copy(ls), |
5288 | isl_dim_set, n_in + i); |
5289 | ma = isl_multi_aff_set_aff(ma, i, aff); |
5290 | } |
5291 | |
5292 | isl_local_space_free(ls); |
5293 | |
5294 | return ma; |
5295 | } |
5296 | |
5297 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map, |
5298 | * taking into account that the dimension at position "d" can be written as |
5299 | * |
5300 | * x = m a + f(..) (1) |
5301 | * |
5302 | * where m is equal to "gcd". |
5303 | * "i" is the index of the equality in "hull" that defines f(..). |
5304 | * In particular, the equality is of the form |
5305 | * |
5306 | * f(..) - x + m g(existentials) = 0 |
5307 | * |
5308 | * or |
5309 | * |
5310 | * -f(..) + x + m g(existentials) = 0 |
5311 | * |
5312 | * We basically plug (1) into "map", resulting in a map with "a" |
5313 | * in the range instead of "x". The corresponding isl_pw_multi_aff |
5314 | * defining "a" is then plugged back into (1) to obtain a definition for "x". |
5315 | * |
5316 | * Specifically, given the input map |
5317 | * |
5318 | * A -> B |
5319 | * |
5320 | * We first wrap it into a set |
5321 | * |
5322 | * [A -> B] |
5323 | * |
5324 | * and define (1) on top of the corresponding space, resulting in "aff". |
5325 | * We use this to create an isl_multi_aff that maps the output position "d" |
5326 | * from "a" to "x", leaving all other (intput and output) dimensions unchanged. |
5327 | * We plug this into the wrapped map, unwrap the result and compute the |
5328 | * corresponding isl_pw_multi_aff. |
5329 | * The result is an expression |
5330 | * |
5331 | * A -> T(A) |
5332 | * |
5333 | * We adjust that to |
5334 | * |
5335 | * A -> [A -> T(A)] |
5336 | * |
5337 | * so that we can plug that into "aff", after extending the latter to |
5338 | * a mapping |
5339 | * |
5340 | * [A -> B] -> B' |
5341 | * |
5342 | * |
5343 | * If "map" is actually a set, then there is no "A" space, meaning |
5344 | * that we do not need to perform any wrapping, and that the result |
5345 | * of the recursive call is of the form |
5346 | * |
5347 | * [T] |
5348 | * |
5349 | * which is plugged into a mapping of the form |
5350 | * |
5351 | * B -> B' |
5352 | */ |
5353 | static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride( |
5354 | __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i, |
5355 | isl_int gcd) |
5356 | { |
5357 | isl_setisl_map *set; |
5358 | isl_space *space; |
5359 | isl_local_space *ls; |
5360 | isl_aff *aff; |
5361 | isl_multi_aff *ma; |
5362 | isl_pw_multi_aff *pma, *id; |
5363 | isl_size n_in; |
5364 | unsigned o_out; |
5365 | isl_size n_out; |
5366 | isl_bool is_set; |
5367 | |
5368 | is_set = isl_map_is_set(map); |
5369 | if (is_set < 0) |
5370 | goto error; |
5371 | |
5372 | n_in = isl_basic_map_dim(hull, isl_dim_in); |
5373 | n_out = isl_basic_map_dim(hull, isl_dim_out); |
5374 | if (n_in < 0 || n_out < 0) |
5375 | goto error; |
5376 | o_out = isl_basic_map_offset(hull, isl_dim_out); |
5377 | |
5378 | if (is_set) |
5379 | set = map; |
5380 | else |
5381 | set = isl_map_wrap(map); |
5382 | space = isl_space_map_from_set(isl_set_get_space(set)); |
5383 | ma = isl_multi_aff_identity(space); |
5384 | ls = isl_local_space_from_space(isl_set_get_space(set)); |
5385 | aff = isl_aff_alloc(ls); |
5386 | if (aff) { |
5387 | isl_int_set_si(aff->v->el[0], 1)isl_sioimath_set_si((aff->v->el[0]), 1); |
5388 | if (isl_int_is_one(hull->eq[i][o_out + d])(isl_sioimath_cmp_si(*(hull->eq[i][o_out + d]), 1) == 0)) |
5389 | isl_seq_neg(aff->v->el + 1, hull->eq[i], |
5390 | aff->v->size - 1); |
5391 | else |
5392 | isl_seq_cpy(aff->v->el + 1, hull->eq[i], |
5393 | aff->v->size - 1); |
5394 | isl_int_set(aff->v->el[1 + o_out + d], gcd)isl_sioimath_set((aff->v->el[1 + o_out + d]), *(gcd)); |
5395 | } |
5396 | ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff)); |
5397 | set = isl_set_preimage_multi_aff(set, ma); |
5398 | |
5399 | ma = range_map(aff, d, n_in, n_out, is_set); |
5400 | |
5401 | if (is_set) |
5402 | map = set; |
5403 | else |
5404 | map = isl_set_unwrap(set); |
5405 | pma = isl_pw_multi_aff_from_map(map); |
5406 | |
5407 | if (!is_set) { |
5408 | space = isl_pw_multi_aff_get_domain_space(pma); |
5409 | space = isl_space_map_from_set(space); |
5410 | id = isl_pw_multi_aff_identity(space); |
5411 | pma = isl_pw_multi_aff_range_product(id, pma); |
5412 | } |
5413 | id = isl_pw_multi_aff_from_multi_aff(ma); |
5414 | pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma); |
5415 | |
5416 | isl_basic_map_free(hull); |
5417 | return pma; |
5418 | error: |
5419 | isl_map_free(map); |
5420 | isl_basic_map_free(hull); |
5421 | return NULL((void*)0); |
5422 | } |
5423 | |
5424 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. |
5425 | * "hull" contains the equalities valid for "map". |
5426 | * |
5427 | * Check if any of the output dimensions is "strided". |
5428 | * That is, we check if it can be written as |
5429 | * |
5430 | * x = m a + f(..) |
5431 | * |
5432 | * with m greater than 1, a some combination of existentially quantified |
5433 | * variables and f an expression in the parameters and input dimensions. |
5434 | * If so, we remove the stride in pw_multi_aff_from_map_stride. |
5435 | * |
5436 | * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further |
5437 | * special case. |
5438 | */ |
5439 | static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides( |
5440 | __isl_take isl_map *map, __isl_take isl_basic_map *hull) |
5441 | { |
5442 | int i, j; |
5443 | isl_size n_out; |
5444 | unsigned o_out; |
5445 | isl_size n_div; |
5446 | unsigned o_div; |
5447 | isl_int gcd; |
5448 | |
5449 | n_div = isl_basic_map_dim(hull, isl_dim_div); |
5450 | n_out = isl_basic_map_dim(hull, isl_dim_out); |
5451 | if (n_div < 0 || n_out < 0) |
5452 | goto error; |
5453 | |
5454 | if (n_div == 0) { |
5455 | isl_basic_map_free(hull); |
5456 | return pw_multi_aff_from_map_check_div(map); |
5457 | } |
5458 | |
5459 | isl_int_init(gcd)isl_sioimath_init((gcd)); |
5460 | |
5461 | o_div = isl_basic_map_offset(hull, isl_dim_div); |
5462 | o_out = isl_basic_map_offset(hull, isl_dim_out); |
5463 | |
5464 | for (i = 0; i < n_out; ++i) { |
5465 | for (j = 0; j < hull->n_eq; ++j) { |
5466 | isl_int *eq = hull->eq[j]; |
5467 | isl_pw_multi_aff *res; |
5468 | |
5469 | if (!isl_int_is_one(eq[o_out + i])(isl_sioimath_cmp_si(*(eq[o_out + i]), 1) == 0) && |
5470 | !isl_int_is_negone(eq[o_out + i])(isl_sioimath_cmp_si(*(eq[o_out + i]), -1) == 0)) |
5471 | continue; |
5472 | if (isl_seq_first_non_zero(eq + o_out, i) != -1) |
5473 | continue; |
5474 | if (isl_seq_first_non_zero(eq + o_out + i + 1, |
5475 | n_out - (i + 1)) != -1) |
5476 | continue; |
5477 | isl_seq_gcd(eq + o_div, n_div, &gcd); |
5478 | if (isl_int_is_zero(gcd)(isl_sioimath_sgn(*(gcd)) == 0)) |
5479 | continue; |
5480 | if (isl_int_is_one(gcd)(isl_sioimath_cmp_si(*(gcd), 1) == 0)) |
5481 | continue; |
5482 | |
5483 | res = pw_multi_aff_from_map_stride(map, hull, |
5484 | i, j, gcd); |
5485 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); |
5486 | return res; |
5487 | } |
5488 | } |
5489 | |
5490 | isl_int_clear(gcd)isl_sioimath_clear((gcd)); |
5491 | isl_basic_map_free(hull); |
5492 | return pw_multi_aff_from_map_check_div(map); |
5493 | error: |
5494 | isl_map_free(map); |
5495 | isl_basic_map_free(hull); |
5496 | return NULL((void*)0); |
5497 | } |
5498 | |
5499 | /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. |
5500 | * |
5501 | * As a special case, we first check if all output dimensions are uniquely |
5502 | * defined in terms of the parameters and input dimensions over the entire |
5503 | * domain. If so, we extract the desired isl_pw_multi_aff directly |
5504 | * from the affine hull of "map" and its domain. |
5505 | * |
5506 | * Otherwise, continue with pw_multi_aff_from_map_check_strides for more |
5507 | * special cases. |
5508 | */ |
5509 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map) |
5510 | { |
5511 | isl_bool sv; |
5512 | isl_size n; |
5513 | isl_basic_map *hull; |
5514 | |
5515 | n = isl_map_n_basic_map(map); |
5516 | if (n < 0) |
5517 | goto error; |
5518 | |
5519 | if (n == 1) { |
5520 | hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); |
5521 | hull = isl_basic_map_plain_affine_hull(hull); |
5522 | sv = isl_basic_map_plain_is_single_valued(hull); |
5523 | if (sv >= 0 && sv) |
5524 | return plain_pw_multi_aff_from_map(isl_map_domain(map), |
5525 | hull); |
5526 | isl_basic_map_free(hull); |
5527 | } |
5528 | map = isl_map_detect_equalities(map); |
5529 | hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); |
5530 | sv = isl_basic_map_plain_is_single_valued(hull); |
5531 | if (sv >= 0 && sv) |
5532 | return plain_pw_multi_aff_from_map(isl_map_domain(map), hull); |
5533 | if (sv >= 0) |
5534 | return pw_multi_aff_from_map_check_strides(map, hull); |
5535 | isl_basic_map_free(hull); |
5536 | error: |
5537 | isl_map_free(map); |
5538 | return NULL((void*)0); |
5539 | } |
5540 | |
5541 | /* This function performs the same operation as isl_pw_multi_aff_from_map, |
5542 | * but is considered as a function on an isl_map when exported. |
5543 | */ |
5544 | __isl_give isl_pw_multi_aff *isl_map_as_pw_multi_aff(__isl_take isl_map *map) |
5545 | { |
5546 | return isl_pw_multi_aff_from_map(map); |
5547 | } |
5548 | |
5549 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_setisl_map *set) |
5550 | { |
5551 | return isl_pw_multi_aff_from_map(set); |
5552 | } |
5553 | |
5554 | /* This function performs the same operation as isl_pw_multi_aff_from_set, |
5555 | * but is considered as a function on an isl_set when exported. |
5556 | */ |
5557 | __isl_give isl_pw_multi_aff *isl_set_as_pw_multi_aff(__isl_take isl_setisl_map *set) |
5558 | { |
5559 | return isl_pw_multi_aff_from_set(set); |
5560 | } |
5561 | |
5562 | /* Convert "map" into an isl_pw_multi_aff (if possible) and |
5563 | * add it to *user. |
5564 | */ |
5565 | static isl_stat pw_multi_aff_from_map(__isl_take isl_map *map, void *user) |
5566 | { |
5567 | isl_union_pw_multi_aff **upma = user; |
5568 | isl_pw_multi_aff *pma; |
5569 | |
5570 | pma = isl_pw_multi_aff_from_map(map); |
5571 | *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma); |
5572 | |
5573 | return *upma ? isl_stat_ok : isl_stat_error; |
5574 | } |
5575 | |
5576 | /* Create an isl_union_pw_multi_aff with the given isl_aff on a universe |
5577 | * domain. |
5578 | */ |
5579 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff( |
5580 | __isl_take isl_aff *aff) |
5581 | { |
5582 | isl_multi_aff *ma; |
5583 | isl_pw_multi_aff *pma; |
5584 | |
5585 | ma = isl_multi_aff_from_aff(aff); |
5586 | pma = isl_pw_multi_aff_from_multi_aff(ma); |
5587 | return isl_union_pw_multi_aff_from_pw_multi_aff(pma); |
5588 | } |
5589 | |
5590 | /* Try and create an isl_union_pw_multi_aff that is equivalent |
5591 | * to the given isl_union_map. |
5592 | * The isl_union_map is required to be single-valued in each space. |
5593 | * Otherwise, an error is produced. |
5594 | */ |
5595 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map( |
5596 | __isl_take isl_union_map *umap) |
5597 | { |
5598 | isl_space *space; |
5599 | isl_union_pw_multi_aff *upma; |
5600 | |
5601 | space = isl_union_map_get_space(umap); |
5602 | upma = isl_union_pw_multi_aff_empty(space); |
5603 | if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0) |
5604 | upma = isl_union_pw_multi_aff_free(upma); |
5605 | isl_union_map_free(umap); |
5606 | |
5607 | return upma; |
5608 | } |
5609 | |
5610 | /* This function performs the same operation as |
5611 | * isl_union_pw_multi_aff_from_union_map, |
5612 | * but is considered as a function on an isl_union_map when exported. |
5613 | */ |
5614 | __isl_give isl_union_pw_multi_aff *isl_union_map_as_union_pw_multi_aff( |
5615 | __isl_take isl_union_map *umap) |
5616 | { |
5617 | return isl_union_pw_multi_aff_from_union_map(umap); |
5618 | } |
5619 | |
5620 | /* Try and create an isl_union_pw_multi_aff that is equivalent |
5621 | * to the given isl_union_set. |
5622 | * The isl_union_set is required to be a singleton in each space. |
5623 | * Otherwise, an error is produced. |
5624 | */ |
5625 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set( |
5626 | __isl_take isl_union_setisl_union_map *uset) |
5627 | { |
5628 | return isl_union_pw_multi_aff_from_union_map(uset); |
5629 | } |
5630 | |
5631 | /* Return the piecewise affine expression "set ? 1 : 0". |
5632 | */ |
5633 | __isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_setisl_map *set) |
5634 | { |
5635 | isl_pw_aff *pa; |
5636 | isl_space *space = isl_set_get_space(set); |
5637 | isl_local_space *ls = isl_local_space_from_space(space); |
5638 | isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls)); |
5639 | isl_aff *one = isl_aff_zero_on_domain(ls); |
5640 | |
5641 | one = isl_aff_add_constant_si(one, 1); |
5642 | pa = isl_pw_aff_alloc(isl_set_copy(set), one); |
5643 | set = isl_set_complement(set); |
5644 | pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero)); |
5645 | |
5646 | return pa; |
5647 | } |
5648 | |
5649 | /* Plug in "subs" for dimension "type", "pos" of "aff". |
5650 | * |
5651 | * Let i be the dimension to replace and let "subs" be of the form |
5652 | * |
5653 | * f/d |
5654 | * |
5655 | * and "aff" of the form |
5656 | * |
5657 | * (a i + g)/m |
5658 | * |
5659 | * The result is |
5660 | * |
5661 | * (a f + d g')/(m d) |
5662 | * |
5663 | * where g' is the result of plugging in "subs" in each of the integer |
5664 | * divisions in g. |
5665 | */ |
5666 | __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff, |
5667 | enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) |
5668 | { |
5669 | isl_ctx *ctx; |
5670 | isl_int v; |
5671 | isl_size n_div; |
5672 | |
5673 | aff = isl_aff_cow(aff); |
5674 | if (!aff || !subs) |
5675 | return isl_aff_free(aff); |
5676 | |
5677 | ctx = isl_aff_get_ctx(aff); |
5678 | if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim)) |
5679 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 5680); return isl_aff_free (aff); } while (0) |
5680 | "spaces don't match", return isl_aff_free(aff))do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 5680); return isl_aff_free (aff); } while (0); |
5681 | n_div = isl_aff_domain_dim(subs, isl_dim_div); |
5682 | if (n_div < 0) |
5683 | return isl_aff_free(aff); |
5684 | if (n_div != 0) |
5685 | isl_die(ctx, isl_error_unsupported,do { isl_handle_error(ctx, isl_error_unsupported, "cannot handle divs yet" , "polly/lib/External/isl/isl_aff.c", 5686); return isl_aff_free (aff); } while (0) |
5686 | "cannot handle divs yet", return isl_aff_free(aff))do { isl_handle_error(ctx, isl_error_unsupported, "cannot handle divs yet" , "polly/lib/External/isl/isl_aff.c", 5686); return isl_aff_free (aff); } while (0); |
5687 | |
5688 | aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs); |
5689 | if (!aff->ls) |
5690 | return isl_aff_free(aff); |
5691 | |
5692 | aff->v = isl_vec_cow(aff->v); |
5693 | if (!aff->v) |
5694 | return isl_aff_free(aff); |
5695 | |
5696 | pos += isl_local_space_offset(aff->ls, type); |
5697 | |
5698 | isl_int_init(v)isl_sioimath_init((v)); |
5699 | isl_seq_substitute(aff->v->el, pos, subs->v->el, |
5700 | aff->v->size, subs->v->size, v); |
5701 | isl_int_clear(v)isl_sioimath_clear((v)); |
5702 | |
5703 | return aff; |
5704 | } |
5705 | |
5706 | /* Plug in "subs" for dimension "type", "pos" in each of the affine |
5707 | * expressions in "maff". |
5708 | */ |
5709 | __isl_give isl_multi_aff *isl_multi_aff_substitute( |
5710 | __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos, |
5711 | __isl_keep isl_aff *subs) |
5712 | { |
5713 | int i; |
5714 | |
5715 | maff = isl_multi_aff_cow(maff); |
5716 | if (!maff || !subs) |
5717 | return isl_multi_aff_free(maff); |
5718 | |
5719 | if (type == isl_dim_in) |
5720 | type = isl_dim_set; |
5721 | |
5722 | for (i = 0; i < maff->n; ++i) { |
5723 | maff->u.p[i] = isl_aff_substitute(maff->u.p[i], |
5724 | type, pos, subs); |
5725 | if (!maff->u.p[i]) |
5726 | return isl_multi_aff_free(maff); |
5727 | } |
5728 | |
5729 | return maff; |
5730 | } |
5731 | |
5732 | /* Plug in "subs" for input dimension "pos" of "pma". |
5733 | * |
5734 | * pma is of the form |
5735 | * |
5736 | * A_i(v) -> M_i(v) |
5737 | * |
5738 | * while subs is of the form |
5739 | * |
5740 | * v' = B_j(v) -> S_j |
5741 | * |
5742 | * Each pair i,j such that C_ij = A_i \cap B_i is non-empty |
5743 | * has a contribution in the result, in particular |
5744 | * |
5745 | * C_ij(S_j) -> M_i(S_j) |
5746 | * |
5747 | * Note that plugging in S_j in C_ij may also result in an empty set |
5748 | * and this contribution should simply be discarded. |
5749 | */ |
5750 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute( |
5751 | __isl_take isl_pw_multi_aff *pma, unsigned pos, |
5752 | __isl_keep isl_pw_aff *subs) |
5753 | { |
5754 | int i, j, n; |
5755 | isl_pw_multi_aff *res; |
5756 | |
5757 | if (!pma || !subs) |
5758 | return isl_pw_multi_aff_free(pma); |
5759 | |
5760 | n = pma->n * subs->n; |
5761 | res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n); |
5762 | |
5763 | for (i = 0; i < pma->n; ++i) { |
5764 | for (j = 0; j < subs->n; ++j) { |
5765 | isl_setisl_map *common; |
5766 | isl_multi_aff *res_ij; |
5767 | int empty; |
5768 | |
5769 | common = isl_set_intersect( |
5770 | isl_set_copy(pma->p[i].set), |
5771 | isl_set_copy(subs->p[j].set)); |
5772 | common = isl_set_substitute(common, |
5773 | pos, subs->p[j].aff); |
5774 | empty = isl_set_plain_is_empty(common); |
5775 | if (empty < 0 || empty) { |
5776 | isl_set_free(common); |
5777 | if (empty < 0) |
5778 | goto error; |
5779 | continue; |
5780 | } |
5781 | |
5782 | res_ij = isl_multi_aff_substitute( |
5783 | isl_multi_aff_copy(pma->p[i].maff), |
5784 | isl_dim_in, pos, subs->p[j].aff); |
5785 | |
5786 | res = isl_pw_multi_aff_add_piece(res, common, res_ij); |
5787 | } |
5788 | } |
5789 | |
5790 | isl_pw_multi_aff_free(pma); |
5791 | return res; |
5792 | error: |
5793 | isl_pw_multi_aff_free(pma); |
5794 | isl_pw_multi_aff_free(res); |
5795 | return NULL((void*)0); |
5796 | } |
5797 | |
5798 | /* Compute the preimage of a range of dimensions in the affine expression "src" |
5799 | * under "ma" and put the result in "dst". The number of dimensions in "src" |
5800 | * that precede the range is given by "n_before". The number of dimensions |
5801 | * in the range is given by the number of output dimensions of "ma". |
5802 | * The number of dimensions that follow the range is given by "n_after". |
5803 | * If "has_denom" is set (to one), |
5804 | * then "src" and "dst" have an extra initial denominator. |
5805 | * "n_div_ma" is the number of existentials in "ma" |
5806 | * "n_div_bset" is the number of existentials in "src" |
5807 | * The resulting "dst" (which is assumed to have been allocated by |
5808 | * the caller) contains coefficients for both sets of existentials, |
5809 | * first those in "ma" and then those in "src". |
5810 | * f, c1, c2 and g are temporary objects that have been initialized |
5811 | * by the caller. |
5812 | * |
5813 | * Let src represent the expression |
5814 | * |
5815 | * (a(p) + f_u u + b v + f_w w + c(divs))/d |
5816 | * |
5817 | * and let ma represent the expressions |
5818 | * |
5819 | * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i |
5820 | * |
5821 | * We start out with the following expression for dst: |
5822 | * |
5823 | * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d |
5824 | * |
5825 | * with the multiplication factor f initially equal to 1 |
5826 | * and f \sum_i b_i v_i kept separately. |
5827 | * For each x_i that we substitute, we multiply the numerator |
5828 | * (and denominator) of dst by c_1 = m_i and add the numerator |
5829 | * of the x_i expression multiplied by c_2 = f b_i, |
5830 | * after removing the common factors of c_1 and c_2. |
5831 | * The multiplication factor f also needs to be multiplied by c_1 |
5832 | * for the next x_j, j > i. |
5833 | */ |
5834 | isl_stat isl_seq_preimage(isl_int *dst, isl_int *src, |
5835 | __isl_keep isl_multi_aff *ma, int n_before, int n_after, |
5836 | int n_div_ma, int n_div_bmap, |
5837 | isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom) |
5838 | { |
5839 | int i; |
5840 | isl_size n_param, n_in, n_out; |
5841 | int o_dst, o_src; |
5842 | |
5843 | n_param = isl_multi_aff_dim(ma, isl_dim_param); |
5844 | n_in = isl_multi_aff_dim(ma, isl_dim_in); |
5845 | n_out = isl_multi_aff_dim(ma, isl_dim_out); |
5846 | if (n_param < 0 || n_in < 0 || n_out < 0) |
5847 | return isl_stat_error; |
5848 | |
5849 | isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before); |
5850 | o_dst = o_src = has_denom + 1 + n_param + n_before; |
5851 | isl_seq_clr(dst + o_dst, n_in); |
5852 | o_dst += n_in; |
5853 | o_src += n_out; |
5854 | isl_seq_cpy(dst + o_dst, src + o_src, n_after); |
5855 | o_dst += n_after; |
5856 | o_src += n_after; |
5857 | isl_seq_clr(dst + o_dst, n_div_ma); |
5858 | o_dst += n_div_ma; |
5859 | isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap); |
5860 | |
5861 | isl_int_set_si(f, 1)isl_sioimath_set_si((f), 1); |
5862 | |
5863 | for (i = 0; i < n_out; ++i) { |
5864 | int offset = has_denom + 1 + n_param + n_before + i; |
5865 | |
5866 | if (isl_int_is_zero(src[offset])(isl_sioimath_sgn(*(src[offset])) == 0)) |
5867 | continue; |
5868 | isl_int_set(c1, ma->u.p[i]->v->el[0])isl_sioimath_set((c1), *(ma->u.p[i]->v->el[0])); |
5869 | isl_int_mul(c2, f, src[offset])isl_sioimath_mul((c2), *(f), *(src[offset])); |
5870 | isl_int_gcd(g, c1, c2)isl_sioimath_gcd((g), *(c1), *(c2)); |
5871 | isl_int_divexact(c1, c1, g)isl_sioimath_tdiv_q((c1), *(c1), *(g)); |
5872 | isl_int_divexact(c2, c2, g)isl_sioimath_tdiv_q((c2), *(c2), *(g)); |
5873 | |
5874 | isl_int_mul(f, f, c1)isl_sioimath_mul((f), *(f), *(c1)); |
5875 | o_dst = has_denom; |
5876 | o_src = 1; |
5877 | isl_seq_combine(dst + o_dst, c1, dst + o_dst, |
5878 | c2, ma->u.p[i]->v->el + o_src, 1 + n_param); |
5879 | o_dst += 1 + n_param; |
5880 | o_src += 1 + n_param; |
5881 | isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before); |
5882 | o_dst += n_before; |
5883 | isl_seq_combine(dst + o_dst, c1, dst + o_dst, |
5884 | c2, ma->u.p[i]->v->el + o_src, n_in); |
5885 | o_dst += n_in; |
5886 | o_src += n_in; |
5887 | isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after); |
5888 | o_dst += n_after; |
5889 | isl_seq_combine(dst + o_dst, c1, dst + o_dst, |
5890 | c2, ma->u.p[i]->v->el + o_src, n_div_ma); |
5891 | o_dst += n_div_ma; |
5892 | o_src += n_div_ma; |
5893 | isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap); |
5894 | if (has_denom) |
5895 | isl_int_mul(dst[0], dst[0], c1)isl_sioimath_mul((dst[0]), *(dst[0]), *(c1)); |
5896 | } |
5897 | |
5898 | return isl_stat_ok; |
5899 | } |
5900 | |
5901 | /* Compute the pullback of "aff" by the function represented by "ma". |
5902 | * In other words, plug in "ma" in "aff". The result is an affine expression |
5903 | * defined over the domain space of "ma". |
5904 | * |
5905 | * If "aff" is represented by |
5906 | * |
5907 | * (a(p) + b x + c(divs))/d |
5908 | * |
5909 | * and ma is represented by |
5910 | * |
5911 | * x = D(p) + F(y) + G(divs') |
5912 | * |
5913 | * then the result is |
5914 | * |
5915 | * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d |
5916 | * |
5917 | * The divs in the local space of the input are similarly adjusted |
5918 | * through a call to isl_local_space_preimage_multi_aff. |
5919 | */ |
5920 | __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff, |
5921 | __isl_take isl_multi_aff *ma) |
5922 | { |
5923 | isl_aff *res = NULL((void*)0); |
5924 | isl_local_space *ls; |
5925 | isl_size n_div_aff, n_div_ma; |
5926 | isl_int f, c1, c2, g; |
5927 | |
5928 | ma = isl_multi_aff_align_divs(ma); |
5929 | if (!aff || !ma) |
5930 | goto error; |
5931 | |
5932 | n_div_aff = isl_aff_dim(aff, isl_dim_div); |
5933 | n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0; |
5934 | if (n_div_aff < 0 || n_div_ma < 0) |
5935 | goto error; |
5936 | |
5937 | ls = isl_aff_get_domain_local_space(aff); |
5938 | ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma)); |
5939 | res = isl_aff_alloc(ls); |
5940 | if (!res) |
5941 | goto error; |
5942 | |
5943 | isl_int_init(f)isl_sioimath_init((f)); |
5944 | isl_int_init(c1)isl_sioimath_init((c1)); |
5945 | isl_int_init(c2)isl_sioimath_init((c2)); |
5946 | isl_int_init(g)isl_sioimath_init((g)); |
5947 | |
5948 | if (isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, |
5949 | n_div_ma, n_div_aff, f, c1, c2, g, 1) < 0) |
5950 | res = isl_aff_free(res); |
5951 | |
5952 | isl_int_clear(f)isl_sioimath_clear((f)); |
5953 | isl_int_clear(c1)isl_sioimath_clear((c1)); |
5954 | isl_int_clear(c2)isl_sioimath_clear((c2)); |
5955 | isl_int_clear(g)isl_sioimath_clear((g)); |
5956 | |
5957 | isl_aff_free(aff); |
5958 | isl_multi_aff_free(ma); |
5959 | res = isl_aff_normalize(res); |
5960 | return res; |
5961 | error: |
5962 | isl_aff_free(aff); |
5963 | isl_multi_aff_free(ma); |
5964 | isl_aff_free(res); |
5965 | return NULL((void*)0); |
5966 | } |
5967 | |
5968 | /* Compute the pullback of "aff1" by the function represented by "aff2". |
5969 | * In other words, plug in "aff2" in "aff1". The result is an affine expression |
5970 | * defined over the domain space of "aff1". |
5971 | * |
5972 | * The domain of "aff1" should match the range of "aff2", which means |
5973 | * that it should be single-dimensional. |
5974 | */ |
5975 | __isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1, |
5976 | __isl_take isl_aff *aff2) |
5977 | { |
5978 | isl_multi_aff *ma; |
5979 | |
5980 | ma = isl_multi_aff_from_aff(aff2); |
5981 | return isl_aff_pullback_multi_aff(aff1, ma); |
5982 | } |
5983 | |
5984 | /* Compute the pullback of "ma1" by the function represented by "ma2". |
5985 | * In other words, plug in "ma2" in "ma1". |
5986 | */ |
5987 | __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff( |
5988 | __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2) |
5989 | { |
5990 | int i; |
5991 | isl_space *space = NULL((void*)0); |
5992 | |
5993 | isl_multi_aff_align_params_bin(&ma1, &ma2); |
5994 | ma2 = isl_multi_aff_align_divs(ma2); |
5995 | ma1 = isl_multi_aff_cow(ma1); |
5996 | if (!ma1 || !ma2) |
5997 | goto error; |
5998 | |
5999 | space = isl_space_join(isl_multi_aff_get_space(ma2), |
6000 | isl_multi_aff_get_space(ma1)); |
6001 | |
6002 | for (i = 0; i < ma1->n; ++i) { |
6003 | ma1->u.p[i] = isl_aff_pullback_multi_aff(ma1->u.p[i], |
6004 | isl_multi_aff_copy(ma2)); |
6005 | if (!ma1->u.p[i]) |
6006 | goto error; |
6007 | } |
6008 | |
6009 | ma1 = isl_multi_aff_reset_space(ma1, space); |
6010 | isl_multi_aff_free(ma2); |
6011 | return ma1; |
6012 | error: |
6013 | isl_space_free(space); |
6014 | isl_multi_aff_free(ma2); |
6015 | isl_multi_aff_free(ma1); |
6016 | return NULL((void*)0); |
6017 | } |
6018 | |
6019 | /* Extend the local space of "dst" to include the divs |
6020 | * in the local space of "src". |
6021 | * |
6022 | * If "src" does not have any divs or if the local spaces of "dst" and |
6023 | * "src" are the same, then no extension is required. |
6024 | */ |
6025 | __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst, |
6026 | __isl_keep isl_aff *src) |
6027 | { |
6028 | isl_ctx *ctx; |
6029 | isl_size src_n_div, dst_n_div; |
6030 | int *exp1 = NULL((void*)0); |
6031 | int *exp2 = NULL((void*)0); |
6032 | isl_bool equal; |
6033 | isl_mat *div; |
6034 | |
6035 | if (!src || !dst) |
6036 | return isl_aff_free(dst); |
6037 | |
6038 | ctx = isl_aff_get_ctx(src); |
6039 | equal = isl_local_space_has_equal_space(src->ls, dst->ls); |
6040 | if (equal < 0) |
6041 | return isl_aff_free(dst); |
6042 | if (!equal) |
6043 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 6044); goto error; } while (0) |
6044 | "spaces don't match", goto error)do { isl_handle_error(ctx, isl_error_invalid, "spaces don't match" , "polly/lib/External/isl/isl_aff.c", 6044); goto error; } while (0); |
6045 | |
6046 | src_n_div = isl_aff_domain_dim(src, isl_dim_div); |
6047 | dst_n_div = isl_aff_domain_dim(dst, isl_dim_div); |
6048 | if (src_n_div == 0) |
6049 | return dst; |
6050 | equal = isl_local_space_is_equal(src->ls, dst->ls); |
6051 | if (equal < 0 || src_n_div < 0 || dst_n_div < 0) |
6052 | return isl_aff_free(dst); |
6053 | if (equal) |
6054 | return dst; |
6055 | |
6056 | exp1 = isl_alloc_array(ctx, int, src_n_div)((int *)isl_malloc_or_die(ctx, (src_n_div)*sizeof(int))); |
6057 | exp2 = isl_alloc_array(ctx, int, dst_n_div)((int *)isl_malloc_or_die(ctx, (dst_n_div)*sizeof(int))); |
6058 | if (!exp1 || (dst_n_div && !exp2)) |
6059 | goto error; |
6060 | |
6061 | div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2); |
6062 | dst = isl_aff_expand_divs(dst, div, exp2); |
6063 | free(exp1); |
6064 | free(exp2); |
6065 | |
6066 | return dst; |
6067 | error: |
6068 | free(exp1); |
6069 | free(exp2); |
6070 | return isl_aff_free(dst); |
6071 | } |
6072 | |
6073 | /* Adjust the local spaces of the affine expressions in "maff" |
6074 | * such that they all have the save divs. |
6075 | */ |
6076 | __isl_give isl_multi_aff *isl_multi_aff_align_divs( |
6077 | __isl_take isl_multi_aff *maff) |
6078 | { |
6079 | int i; |
6080 | |
6081 | if (!maff) |
6082 | return NULL((void*)0); |
6083 | if (maff->n == 0) |
6084 | return maff; |
6085 | maff = isl_multi_aff_cow(maff); |
6086 | if (!maff) |
6087 | return NULL((void*)0); |
6088 | |
6089 | for (i = 1; i < maff->n; ++i) |
6090 | maff->u.p[0] = isl_aff_align_divs(maff->u.p[0], maff->u.p[i]); |
6091 | for (i = 1; i < maff->n; ++i) { |
6092 | maff->u.p[i] = isl_aff_align_divs(maff->u.p[i], maff->u.p[0]); |
6093 | if (!maff->u.p[i]) |
6094 | return isl_multi_aff_free(maff); |
6095 | } |
6096 | |
6097 | return maff; |
6098 | } |
6099 | |
6100 | __isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff) |
6101 | { |
6102 | aff = isl_aff_cow(aff); |
6103 | if (!aff) |
6104 | return NULL((void*)0); |
6105 | |
6106 | aff->ls = isl_local_space_lift(aff->ls); |
6107 | if (!aff->ls) |
6108 | return isl_aff_free(aff); |
6109 | |
6110 | return aff; |
6111 | } |
6112 | |
6113 | /* Lift "maff" to a space with extra dimensions such that the result |
6114 | * has no more existentially quantified variables. |
6115 | * If "ls" is not NULL, then *ls is assigned the local space that lies |
6116 | * at the basis of the lifting applied to "maff". |
6117 | */ |
6118 | __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff, |
6119 | __isl_give isl_local_space **ls) |
6120 | { |
6121 | int i; |
6122 | isl_space *space; |
6123 | isl_size n_div; |
6124 | |
6125 | if (ls) |
6126 | *ls = NULL((void*)0); |
6127 | |
6128 | if (!maff) |
6129 | return NULL((void*)0); |
6130 | |
6131 | if (maff->n == 0) { |
6132 | if (ls) { |
6133 | isl_space *space = isl_multi_aff_get_domain_space(maff); |
6134 | *ls = isl_local_space_from_space(space); |
6135 | if (!*ls) |
6136 | return isl_multi_aff_free(maff); |
6137 | } |
6138 | return maff; |
6139 | } |
6140 | |
6141 | maff = isl_multi_aff_cow(maff); |
6142 | maff = isl_multi_aff_align_divs(maff); |
6143 | if (!maff) |
6144 | return NULL((void*)0); |
6145 | |
6146 | n_div = isl_aff_dim(maff->u.p[0], isl_dim_div); |
6147 | if (n_div < 0) |
6148 | return isl_multi_aff_free(maff); |
6149 | space = isl_multi_aff_get_space(maff); |
6150 | space = isl_space_lift(isl_space_domain(space), n_div); |
6151 | space = isl_space_extend_domain_with_range(space, |
6152 | isl_multi_aff_get_space(maff)); |
6153 | if (!space) |
6154 | return isl_multi_aff_free(maff); |
6155 | isl_space_free(maff->space); |
6156 | maff->space = space; |
6157 | |
6158 | if (ls) { |
6159 | *ls = isl_aff_get_domain_local_space(maff->u.p[0]); |
6160 | if (!*ls) |
6161 | return isl_multi_aff_free(maff); |
6162 | } |
6163 | |
6164 | for (i = 0; i < maff->n; ++i) { |
6165 | maff->u.p[i] = isl_aff_lift(maff->u.p[i]); |
6166 | if (!maff->u.p[i]) |
6167 | goto error; |
6168 | } |
6169 | |
6170 | return maff; |
6171 | error: |
6172 | if (ls) |
6173 | isl_local_space_free(*ls); |
6174 | return isl_multi_aff_free(maff); |
6175 | } |
6176 | |
6177 | #undef TYPEisl_multi_union_pw_aff |
6178 | #define TYPEisl_multi_union_pw_aff isl_pw_multi_aff |
6179 | static |
6180 | #include "check_type_range_templ.c" |
6181 | |
6182 | /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma". |
6183 | */ |
6184 | __isl_give isl_pw_aff *isl_pw_multi_aff_get_at( |
6185 | __isl_keep isl_pw_multi_aff *pma, int pos) |
6186 | { |
6187 | int i; |
6188 | isl_size n_out; |
6189 | isl_space *space; |
6190 | isl_pw_aff *pa; |
6191 | |
6192 | if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0) |
6193 | return NULL((void*)0); |
6194 | |
6195 | n_out = isl_pw_multi_aff_dim(pma, isl_dim_out); |
6196 | if (n_out < 0) |
6197 | return NULL((void*)0); |
6198 | |
6199 | space = isl_pw_multi_aff_get_space(pma); |
6200 | space = isl_space_drop_dims(space, isl_dim_out, |
6201 | pos + 1, n_out - pos - 1); |
6202 | space = isl_space_drop_dims(space, isl_dim_out, 0, pos); |
6203 | |
6204 | pa = isl_pw_aff_alloc_size(space, pma->n); |
6205 | for (i = 0; i < pma->n; ++i) { |
6206 | isl_aff *aff; |
6207 | aff = isl_multi_aff_get_aff(pma->p[i].maff, pos); |
6208 | pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff); |
6209 | } |
6210 | |
6211 | return pa; |
6212 | } |
6213 | |
6214 | /* This is an alternative name for the function above. |
6215 | */ |
6216 | __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff( |
6217 | __isl_keep isl_pw_multi_aff *pma, int pos) |
6218 | { |
6219 | return isl_pw_multi_aff_get_at(pma, pos); |
6220 | } |
6221 | |
6222 | /* Return an isl_pw_multi_aff with the given "set" as domain and |
6223 | * an unnamed zero-dimensional range. |
6224 | */ |
6225 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain( |
6226 | __isl_take isl_setisl_map *set) |
6227 | { |
6228 | isl_multi_aff *ma; |
6229 | isl_space *space; |
6230 | |
6231 | space = isl_set_get_space(set); |
6232 | space = isl_space_from_domain(space); |
6233 | ma = isl_multi_aff_zero(space); |
6234 | return isl_pw_multi_aff_alloc(set, ma); |
6235 | } |
6236 | |
6237 | /* Add an isl_pw_multi_aff with the given "set" as domain and |
6238 | * an unnamed zero-dimensional range to *user. |
6239 | */ |
6240 | static isl_stat add_pw_multi_aff_from_domain(__isl_take isl_setisl_map *set, |
6241 | void *user) |
6242 | { |
6243 | isl_union_pw_multi_aff **upma = user; |
6244 | isl_pw_multi_aff *pma; |
6245 | |
6246 | pma = isl_pw_multi_aff_from_domain(set); |
6247 | *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma); |
6248 | |
6249 | return isl_stat_ok; |
6250 | } |
6251 | |
6252 | /* Return an isl_union_pw_multi_aff with the given "uset" as domain and |
6253 | * an unnamed zero-dimensional range. |
6254 | */ |
6255 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain( |
6256 | __isl_take isl_union_setisl_union_map *uset) |
6257 | { |
6258 | isl_space *space; |
6259 | isl_union_pw_multi_aff *upma; |
6260 | |
6261 | if (!uset) |
6262 | return NULL((void*)0); |
6263 | |
6264 | space = isl_union_set_get_space(uset); |
6265 | upma = isl_union_pw_multi_aff_empty(space); |
6266 | |
6267 | if (isl_union_set_foreach_set(uset, |
6268 | &add_pw_multi_aff_from_domain, &upma) < 0) |
6269 | goto error; |
6270 | |
6271 | isl_union_set_free(uset); |
6272 | return upma; |
6273 | error: |
6274 | isl_union_set_free(uset); |
6275 | isl_union_pw_multi_aff_free(upma); |
6276 | return NULL((void*)0); |
6277 | } |
6278 | |
6279 | /* Local data for bin_entry and the callback "fn". |
6280 | */ |
6281 | struct isl_union_pw_multi_aff_bin_data { |
6282 | isl_union_pw_multi_aff *upma2; |
6283 | isl_union_pw_multi_aff *res; |
6284 | isl_pw_multi_aff *pma; |
6285 | isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user); |
6286 | }; |
6287 | |
6288 | /* Given an isl_pw_multi_aff from upma1, store it in data->pma |
6289 | * and call data->fn for each isl_pw_multi_aff in data->upma2. |
6290 | */ |
6291 | static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user) |
6292 | { |
6293 | struct isl_union_pw_multi_aff_bin_data *data = user; |
6294 | isl_stat r; |
6295 | |
6296 | data->pma = pma; |
6297 | r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2, |
6298 | data->fn, data); |
6299 | isl_pw_multi_aff_free(pma); |
6300 | |
6301 | return r; |
6302 | } |
6303 | |
6304 | /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2". |
6305 | * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is |
6306 | * passed as user field) and the isl_pw_multi_aff from upma2 is available |
6307 | * as *entry. The callback should adjust data->res if desired. |
6308 | */ |
6309 | static __isl_give isl_union_pw_multi_aff *bin_op( |
6310 | __isl_take isl_union_pw_multi_aff *upma1, |
6311 | __isl_take isl_union_pw_multi_aff *upma2, |
6312 | isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user)) |
6313 | { |
6314 | isl_space *space; |
6315 | struct isl_union_pw_multi_aff_bin_data data = { NULL((void*)0), NULL((void*)0), NULL((void*)0), fn }; |
6316 | |
6317 | space = isl_union_pw_multi_aff_get_space(upma2); |
6318 | upma1 = isl_union_pw_multi_aff_align_params(upma1, space); |
6319 | space = isl_union_pw_multi_aff_get_space(upma1); |
6320 | upma2 = isl_union_pw_multi_aff_align_params(upma2, space); |
6321 | |
6322 | if (!upma1 || !upma2) |
6323 | goto error; |
6324 | |
6325 | data.upma2 = upma2; |
6326 | data.res = isl_union_pw_multi_aff_alloc_same_size(upma1); |
6327 | if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1, |
6328 | &bin_entry, &data) < 0) |
6329 | goto error; |
6330 | |
6331 | isl_union_pw_multi_aff_free(upma1); |
6332 | isl_union_pw_multi_aff_free(upma2); |
6333 | return data.res; |
6334 | error: |
6335 | isl_union_pw_multi_aff_free(upma1); |
6336 | isl_union_pw_multi_aff_free(upma2); |
6337 | isl_union_pw_multi_aff_free(data.res); |
6338 | return NULL((void*)0); |
6339 | } |
6340 | |
6341 | /* Given two isl_pw_multi_affs A -> B and C -> D, |
6342 | * construct an isl_pw_multi_aff (A * C) -> [B -> D]. |
6343 | */ |
6344 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product( |
6345 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
6346 | { |
6347 | isl_space *space; |
6348 | |
6349 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
6350 | space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1), |
6351 | isl_pw_multi_aff_get_space(pma2)); |
6352 | return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space, |
6353 | &isl_multi_aff_range_product); |
6354 | } |
6355 | |
6356 | /* Given two isl_pw_multi_affs A -> B and C -> D, |
6357 | * construct an isl_pw_multi_aff (A * C) -> (B, D). |
6358 | */ |
6359 | __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product( |
6360 | __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) |
6361 | { |
6362 | isl_space *space; |
6363 | |
6364 | isl_pw_multi_aff_align_params_bin(&pma1, &pma2); |
6365 | space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1), |
6366 | isl_pw_multi_aff_get_space(pma2)); |
6367 | space = isl_space_flatten_range(space); |
6368 | return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space, |
6369 | &isl_multi_aff_flat_range_product); |
6370 | } |
6371 | |
6372 | /* If data->pma and "pma2" have the same domain space, then use "range_product" |
6373 | * to compute some form of range product and add the result to data->res. |
6374 | */ |
6375 | static isl_stat gen_range_product_entry(__isl_take isl_pw_multi_aff *pma2, |
6376 | __isl_give isl_pw_multi_aff *(*range_product)( |
6377 | __isl_take isl_pw_multi_aff *pma1, |
6378 | __isl_take isl_pw_multi_aff *pma2), |
6379 | void *user) |
6380 | { |
6381 | struct isl_union_pw_multi_aff_bin_data *data = user; |
6382 | isl_bool match; |
6383 | isl_space *space1, *space2; |
6384 | |
6385 | space1 = isl_pw_multi_aff_peek_space(data->pma); |
6386 | space2 = isl_pw_multi_aff_peek_space(pma2); |
6387 | match = isl_space_tuple_is_equal(space1, isl_dim_in, |
6388 | space2, isl_dim_in); |
6389 | if (match < 0 || !match) { |
6390 | isl_pw_multi_aff_free(pma2); |
6391 | return match < 0 ? isl_stat_error : isl_stat_ok; |
6392 | } |
6393 | |
6394 | pma2 = range_product(isl_pw_multi_aff_copy(data->pma), pma2); |
6395 | |
6396 | data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2); |
6397 | |
6398 | return isl_stat_ok; |
6399 | } |
6400 | |
6401 | /* If data->pma and "pma2" have the same domain space, then compute |
6402 | * their flat range product and add the result to data->res. |
6403 | */ |
6404 | static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2, |
6405 | void *user) |
6406 | { |
6407 | return gen_range_product_entry(pma2, |
6408 | &isl_pw_multi_aff_flat_range_product, user); |
6409 | } |
6410 | |
6411 | /* Given two isl_union_pw_multi_affs A -> B and C -> D, |
6412 | * construct an isl_union_pw_multi_aff (A * C) -> (B, D). |
6413 | */ |
6414 | __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product( |
6415 | __isl_take isl_union_pw_multi_aff *upma1, |
6416 | __isl_take isl_union_pw_multi_aff *upma2) |
6417 | { |
6418 | return bin_op(upma1, upma2, &flat_range_product_entry); |
6419 | } |
6420 | |
6421 | /* If data->pma and "pma2" have the same domain space, then compute |
6422 | * their range product and add the result to data->res. |
6423 | */ |
6424 | static isl_stat range_product_entry(__isl_take isl_pw_multi_aff *pma2, |
6425 | void *user) |
6426 | { |
6427 | return gen_range_product_entry(pma2, |
6428 | &isl_pw_multi_aff_range_product, user); |
6429 | } |
6430 | |
6431 | /* Given two isl_union_pw_multi_affs A -> B and C - |