File: | build/source/polly/lib/External/isl/isl_pw_templ.c |
Warning: | line 544, column 2 Value stored to 'ctx' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright 2010-2011 INRIA Saclay |
3 | * Copyright 2011 Sven Verdoolaege |
4 | * Copyright 2012-2014 Ecole Normale Superieure |
5 | * |
6 | * Use of this software is governed by the MIT license |
7 | * |
8 | * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, |
9 | * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, |
10 | * 91893 Orsay, France |
11 | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France |
12 | */ |
13 | |
14 | #include <isl/id.h> |
15 | #include <isl/aff.h> |
16 | #include <isl_sort.h> |
17 | #include <isl_val_private.h> |
18 | |
19 | #include <isl_pw_macro.h> |
20 | |
21 | #include "opt_type.h" |
22 | |
23 | __isl_give PWisl_pw_qpolynomial *FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(__isl_take isl_space *space |
24 | OPT_TYPE_PARAM, int n) |
25 | { |
26 | isl_ctx *ctx; |
27 | struct PWisl_pw_qpolynomial *pw; |
28 | |
29 | if (!space) |
30 | return NULL((void*)0); |
31 | ctx = isl_space_get_ctx(space); |
32 | isl_assert(ctx, n >= 0, goto error)do { if (n >= 0) break; do { isl_handle_error(ctx, isl_error_unknown , "Assertion \"" "n >= 0" "\" failed", "polly/lib/External/isl/isl_pw_templ.c" , 32); goto error; } while (0); } while (0); |
33 | pw = isl_alloc(ctx, struct PW,((struct isl_pw_qpolynomial *)isl_malloc_or_die(ctx, sizeof(struct isl_pw_qpolynomial) + (n - 1) * sizeof(struct isl_pw_qpolynomial_piece ))) |
34 | sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)))((struct isl_pw_qpolynomial *)isl_malloc_or_die(ctx, sizeof(struct isl_pw_qpolynomial) + (n - 1) * sizeof(struct isl_pw_qpolynomial_piece ))); |
35 | if (!pw) |
36 | goto error; |
37 | |
38 | pw->ref = 1; |
39 | OPT_SET_TYPE(pw->, type); |
40 | pw->size = n; |
41 | pw->n = 0; |
42 | pw->dim = space; |
43 | return pw; |
44 | error: |
45 | isl_space_free(space); |
46 | return NULL((void*)0); |
47 | } |
48 | |
49 | __isl_give PWisl_pw_qpolynomial *FN(PW,ZERO)isl_pw_qpolynomial_zero(__isl_take isl_space *space OPT_TYPE_PARAM) |
50 | { |
51 | return FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(space OPT_TYPE_ARG(NO_LOC), 0); |
52 | } |
53 | |
54 | /* Add a piece with domain "set" and base expression "el" |
55 | * to the piecewise expression "pw". |
56 | * |
57 | * Do this independently of the values of "set" and "el", |
58 | * such that this function can be used by isl_pw_*_dup. |
59 | */ |
60 | __isl_give PWisl_pw_qpolynomial *FN(PW,add_dup_piece)isl_pw_qpolynomial_add_dup_piece(__isl_take PWisl_pw_qpolynomial *pw, |
61 | __isl_take isl_setisl_map *set, __isl_take ELisl_pw_qpolynomial *el) |
62 | { |
63 | isl_ctx *ctx; |
64 | isl_space *el_dim = NULL((void*)0); |
65 | |
66 | if (!pw || !set || !el) |
67 | goto error; |
68 | |
69 | ctx = isl_set_get_ctx(set); |
70 | if (!OPT_EQUAL_TYPES(pw->, el->)1) |
71 | isl_die(ctx, isl_error_invalid, "fold types don't match",do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 72); goto error; } while (0) |
72 | goto error)do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 72); goto error; } while (0); |
73 | el_dim = FN(EL,get_space(el))isl_pw_qpolynomial_get_space(el); |
74 | isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error)do { if (isl_space_is_equal(pw->dim, el_dim)) break; do { isl_handle_error (ctx, isl_error_unknown, "Assertion \"" "isl_space_is_equal(pw->dim, el_dim)" "\" failed", "polly/lib/External/isl/isl_pw_templ.c", 74); goto error; } while (0); } while (0); |
75 | isl_assert(ctx, pw->n < pw->size, goto error)do { if (pw->n < pw->size) break; do { isl_handle_error (ctx, isl_error_unknown, "Assertion \"" "pw->n < pw->size" "\" failed", "polly/lib/External/isl/isl_pw_templ.c", 75); goto error; } while (0); } while (0); |
76 | |
77 | pw->p[pw->n].set = set; |
78 | pw->p[pw->n].FIELDqp = el; |
79 | pw->n++; |
80 | |
81 | isl_space_free(el_dim); |
82 | return pw; |
83 | error: |
84 | isl_space_free(el_dim); |
85 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
86 | isl_set_free(set); |
87 | FN(EL,free)isl_pw_qpolynomial_free(el); |
88 | return NULL((void*)0); |
89 | } |
90 | |
91 | /* Add a piece with domain "set" and base expression "el" |
92 | * to the piecewise expression "pw", provided the domain |
93 | * is not obviously empty and the base expression |
94 | * is not equal to the default value. |
95 | */ |
96 | __isl_give PWisl_pw_qpolynomial *FN(PW,add_piece)isl_pw_qpolynomial_add_piece(__isl_take PWisl_pw_qpolynomial *pw, |
97 | __isl_take isl_setisl_map *set, __isl_take ELisl_pw_qpolynomial *el) |
98 | { |
99 | isl_bool skip; |
100 | |
101 | skip = isl_set_plain_is_empty(set); |
102 | if (skip >= 0 && !skip) |
103 | skip = FN(EL,EL_IS_ZERO)isl_pw_qpolynomial_is_zero(el); |
104 | if (skip >= 0 && !skip) |
105 | return FN(PW,add_dup_piece)isl_pw_qpolynomial_add_dup_piece(pw, set, el); |
106 | |
107 | isl_set_free(set); |
108 | FN(EL,free)isl_pw_qpolynomial_free(el); |
109 | if (skip < 0) |
110 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
111 | return pw; |
112 | } |
113 | |
114 | /* Does the space of "set" correspond to that of the domain of "el". |
115 | */ |
116 | static isl_bool FN(PW,compatible_domain)isl_pw_qpolynomial_compatible_domain(__isl_keep ELisl_pw_qpolynomial *el, |
117 | __isl_keep isl_setisl_map *set) |
118 | { |
119 | isl_bool ok; |
120 | isl_space *el_space, *set_space; |
121 | |
122 | if (!set || !el) |
123 | return isl_bool_error; |
124 | set_space = isl_set_get_space(set); |
125 | el_space = FN(EL,get_space)isl_pw_qpolynomial_get_space(el); |
126 | ok = isl_space_is_domain_internal(set_space, el_space); |
127 | isl_space_free(el_space); |
128 | isl_space_free(set_space); |
129 | return ok; |
130 | } |
131 | |
132 | /* Check that the space of "set" corresponds to that of the domain of "el". |
133 | */ |
134 | static isl_stat FN(PW,check_compatible_domain)isl_pw_qpolynomial_check_compatible_domain(__isl_keep ELisl_pw_qpolynomial *el, |
135 | __isl_keep isl_setisl_map *set) |
136 | { |
137 | isl_bool ok; |
138 | |
139 | ok = FN(PW,compatible_domain)isl_pw_qpolynomial_compatible_domain(el, set); |
140 | if (ok < 0) |
141 | return isl_stat_error; |
142 | if (!ok) |
143 | isl_die(isl_set_get_ctx(set), isl_error_invalid,do { isl_handle_error(isl_set_get_ctx(set), isl_error_invalid , "incompatible spaces", "polly/lib/External/isl/isl_pw_templ.c" , 144); return isl_stat_error; } while (0) |
144 | "incompatible spaces", return isl_stat_error)do { isl_handle_error(isl_set_get_ctx(set), isl_error_invalid , "incompatible spaces", "polly/lib/External/isl/isl_pw_templ.c" , 144); return isl_stat_error; } while (0); |
145 | |
146 | return isl_stat_ok; |
147 | } |
148 | |
149 | __isl_give PWisl_pw_qpolynomial *FN(PW,alloc)isl_pw_qpolynomial_alloc(OPT_TYPE_PARAM_FIRST |
150 | __isl_take isl_setisl_map *set, __isl_take ELisl_pw_qpolynomial *el) |
151 | { |
152 | PWisl_pw_qpolynomial *pw; |
153 | |
154 | if (FN(PW,check_compatible_domain)isl_pw_qpolynomial_check_compatible_domain(el, set) < 0) |
155 | goto error; |
156 | |
157 | pw = FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(FN(EL,get_space)isl_pw_qpolynomial_get_space(el) OPT_TYPE_ARG(NO_LOC), 1); |
158 | |
159 | return FN(PW,add_piece)isl_pw_qpolynomial_add_piece(pw, set, el); |
160 | error: |
161 | isl_set_free(set); |
162 | FN(EL,free)isl_pw_qpolynomial_free(el); |
163 | return NULL((void*)0); |
164 | } |
165 | |
166 | __isl_give PWisl_pw_qpolynomial *FN(PW,dup)isl_pw_qpolynomial_dup(__isl_keep PWisl_pw_qpolynomial *pw) |
167 | { |
168 | int i; |
169 | PWisl_pw_qpolynomial *dup; |
170 | |
171 | if (!pw) |
172 | return NULL((void*)0); |
173 | |
174 | dup = FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(isl_space_copy(pw->dim) |
175 | OPT_TYPE_ARG(pw->), pw->n); |
176 | if (!dup) |
177 | return NULL((void*)0); |
178 | |
179 | for (i = 0; i < pw->n; ++i) |
180 | dup = FN(PW,add_dup_piece)isl_pw_qpolynomial_add_dup_piece(dup, isl_set_copy(pw->p[i].set), |
181 | FN(EL,copy)isl_pw_qpolynomial_copy(pw->p[i].FIELDqp)); |
182 | |
183 | return dup; |
184 | } |
185 | |
186 | __isl_give PWisl_pw_qpolynomial *FN(PW,cow)isl_pw_qpolynomial_cow(__isl_take PWisl_pw_qpolynomial *pw) |
187 | { |
188 | if (!pw) |
189 | return NULL((void*)0); |
190 | |
191 | if (pw->ref == 1) |
192 | return pw; |
193 | pw->ref--; |
194 | return FN(PW,dup)isl_pw_qpolynomial_dup(pw); |
195 | } |
196 | |
197 | __isl_give PWisl_pw_qpolynomial *FN(PW,copy)isl_pw_qpolynomial_copy(__isl_keep PWisl_pw_qpolynomial *pw) |
198 | { |
199 | if (!pw) |
200 | return NULL((void*)0); |
201 | |
202 | pw->ref++; |
203 | return pw; |
204 | } |
205 | |
206 | __isl_null PWisl_pw_qpolynomial *FN(PW,free)isl_pw_qpolynomial_free(__isl_take PWisl_pw_qpolynomial *pw) |
207 | { |
208 | int i; |
209 | |
210 | if (!pw) |
211 | return NULL((void*)0); |
212 | if (--pw->ref > 0) |
213 | return NULL((void*)0); |
214 | |
215 | for (i = 0; i < pw->n; ++i) { |
216 | isl_set_free(pw->p[i].set); |
217 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[i].FIELDqp); |
218 | } |
219 | isl_space_free(pw->dim); |
220 | free(pw); |
221 | |
222 | return NULL((void*)0); |
223 | } |
224 | |
225 | /* Create a piecewise expression with the given base expression on a universe |
226 | * domain. |
227 | */ |
228 | static __isl_give PWisl_pw_qpolynomial *FN(FN(FN(PW,from),BASE),type_base)isl_pw_qpolynomial_from_pw_qpolynomial_type_base(__isl_take ELisl_pw_qpolynomial *el |
229 | OPT_TYPE_PARAM) |
230 | { |
231 | isl_setisl_map *dom = isl_set_universe(FN(EL,get_domain_space)isl_pw_qpolynomial_get_domain_space(el)); |
232 | return FN(PW,alloc)isl_pw_qpolynomial_alloc(OPT_TYPE_ARG_FIRST(NO_LOC) dom, el); |
233 | } |
234 | |
235 | /* Create a piecewise expression with the given base expression on a universe |
236 | * domain. |
237 | * |
238 | * If the default value of this piecewise type is zero and |
239 | * if "el" is effectively zero, then create an empty piecewise expression |
240 | * instead. |
241 | */ |
242 | static __isl_give PWisl_pw_qpolynomial *FN(FN(FN(PW,from),BASE),type)isl_pw_qpolynomial_from_pw_qpolynomial_type(__isl_take ELisl_pw_qpolynomial *el |
243 | OPT_TYPE_PARAM) |
244 | { |
245 | isl_bool is_zero; |
246 | isl_space *space; |
247 | |
248 | if (!DEFAULT_IS_ZERO1) |
249 | return FN(FN(FN(PW,from),BASE),type_base)isl_pw_qpolynomial_from_pw_qpolynomial_type_base(el |
250 | OPT_TYPE_ARG(NO_LOC)); |
251 | is_zero = FN(EL,EL_IS_ZERO)isl_pw_qpolynomial_is_zero(el); |
252 | if (is_zero < 0) |
253 | goto error; |
254 | if (!is_zero) |
255 | return FN(FN(FN(PW,from),BASE),type_base)isl_pw_qpolynomial_from_pw_qpolynomial_type_base(el |
256 | OPT_TYPE_ARG(NO_LOC)); |
257 | space = FN(EL,get_space)isl_pw_qpolynomial_get_space(el); |
258 | FN(EL,free)isl_pw_qpolynomial_free(el); |
259 | return FN(PW,ZERO)isl_pw_qpolynomial_zero(space OPT_TYPE_ARG(NO_LOC)); |
260 | error: |
261 | FN(EL,free)isl_pw_qpolynomial_free(el); |
262 | return NULL((void*)0); |
263 | } |
264 | |
265 | #ifdef HAS_TYPE |
266 | /* Create a piecewise expression with the given base expression on a universe |
267 | * domain. |
268 | * |
269 | * Pass along the type as an extra argument for improved uniformity |
270 | * with piecewise types that do not have a fold type. |
271 | */ |
272 | __isl_give PWisl_pw_qpolynomial *FN(FN(PW,from),BASE)isl_pw_qpolynomial_from_pw_qpolynomial(__isl_take ELisl_pw_qpolynomial *el) |
273 | { |
274 | enum isl_fold type = FN(EL,get_type)isl_pw_qpolynomial_get_type(el); |
275 | return FN(FN(FN(PW,from),BASE),type)isl_pw_qpolynomial_from_pw_qpolynomial_type(el, type); |
276 | } |
277 | #else |
278 | __isl_give PWisl_pw_qpolynomial *FN(FN(PW,from),BASE)isl_pw_qpolynomial_from_pw_qpolynomial(__isl_take ELisl_pw_qpolynomial *el) |
279 | { |
280 | return FN(FN(FN(PW,from),BASE),type)isl_pw_qpolynomial_from_pw_qpolynomial_type(el); |
281 | } |
282 | #endif |
283 | |
284 | const char *FN(PW,get_dim_name)isl_pw_qpolynomial_get_dim_name(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
285 | unsigned pos) |
286 | { |
287 | return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL((void*)0); |
288 | } |
289 | |
290 | isl_bool FN(PW,has_dim_id)isl_pw_qpolynomial_has_dim_id(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
291 | unsigned pos) |
292 | { |
293 | return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error; |
294 | } |
295 | |
296 | __isl_give isl_id *FN(PW,get_dim_id)isl_pw_qpolynomial_get_dim_id(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
297 | unsigned pos) |
298 | { |
299 | return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL((void*)0); |
300 | } |
301 | |
302 | isl_bool FN(PW,has_tuple_name)isl_pw_qpolynomial_has_tuple_name(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
303 | { |
304 | return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error; |
305 | } |
306 | |
307 | const char *FN(PW,get_tuple_name)isl_pw_qpolynomial_get_tuple_name(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
308 | { |
309 | return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL((void*)0); |
310 | } |
311 | |
312 | isl_bool FN(PW,has_tuple_id)isl_pw_qpolynomial_has_tuple_id(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
313 | { |
314 | return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error; |
315 | } |
316 | |
317 | __isl_give isl_id *FN(PW,get_tuple_id)isl_pw_qpolynomial_get_tuple_id(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
318 | { |
319 | return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL((void*)0); |
320 | } |
321 | |
322 | isl_bool FN(PW,IS_ZERO)isl_pw_qpolynomial_is_zero(__isl_keep PWisl_pw_qpolynomial *pw) |
323 | { |
324 | if (!pw) |
325 | return isl_bool_error; |
326 | |
327 | return isl_bool_ok(pw->n == 0); |
328 | } |
329 | |
330 | __isl_give PWisl_pw_qpolynomial *FN(PW,realign_domain)isl_pw_qpolynomial_realign_domain(__isl_take PWisl_pw_qpolynomial *pw, |
331 | __isl_take isl_reordering *exp) |
332 | { |
333 | int i; |
334 | |
335 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
336 | if (!pw || !exp) |
337 | goto error; |
338 | |
339 | for (i = 0; i < pw->n; ++i) { |
340 | pw->p[i].set = isl_set_realign(pw->p[i].set, |
341 | isl_reordering_copy(exp)); |
342 | if (!pw->p[i].set) |
343 | goto error; |
344 | pw->p[i].FIELDqp = FN(EL,realign_domain)isl_pw_qpolynomial_realign_domain(pw->p[i].FIELDqp, |
345 | isl_reordering_copy(exp)); |
346 | if (!pw->p[i].FIELDqp) |
347 | goto error; |
348 | } |
349 | |
350 | pw = FN(PW,reset_domain_space)isl_pw_qpolynomial_reset_domain_space(pw, isl_reordering_get_space(exp)); |
351 | |
352 | isl_reordering_free(exp); |
353 | return pw; |
354 | error: |
355 | isl_reordering_free(exp); |
356 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
357 | return NULL((void*)0); |
358 | } |
359 | |
360 | #undef TYPEisl_term |
361 | #define TYPEisl_term PWisl_pw_qpolynomial |
362 | |
363 | #include "isl_check_named_params_templ.c" |
364 | |
365 | /* Align the parameters of "pw" to those of "model". |
366 | */ |
367 | __isl_give PWisl_pw_qpolynomial *FN(PW,align_params)isl_pw_qpolynomial_align_params(__isl_take PWisl_pw_qpolynomial *pw, __isl_take isl_space *model) |
368 | { |
369 | isl_ctx *ctx; |
370 | isl_bool equal_params; |
371 | |
372 | if (!pw || !model) |
373 | goto error; |
374 | |
375 | ctx = isl_space_get_ctx(model); |
376 | if (!isl_space_has_named_params(model)) |
377 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "model has unnamed parameters" , "polly/lib/External/isl/isl_pw_templ.c", 378); goto error; } while (0) |
378 | "model has unnamed parameters", goto error)do { isl_handle_error(ctx, isl_error_invalid, "model has unnamed parameters" , "polly/lib/External/isl/isl_pw_templ.c", 378); goto error; } while (0); |
379 | if (FN(PW,check_named_params)isl_pw_qpolynomial_check_named_params(pw) < 0) |
380 | goto error; |
381 | equal_params = isl_space_has_equal_params(pw->dim, model); |
382 | if (equal_params < 0) |
383 | goto error; |
384 | if (!equal_params) { |
385 | isl_reordering *exp; |
386 | |
387 | exp = isl_parameter_alignment_reordering(pw->dim, model); |
388 | exp = isl_reordering_extend_space(exp, |
389 | FN(PW,get_domain_space)isl_pw_qpolynomial_get_domain_space(pw)); |
390 | pw = FN(PW,realign_domain)isl_pw_qpolynomial_realign_domain(pw, exp); |
391 | } |
392 | |
393 | isl_space_free(model); |
394 | return pw; |
395 | error: |
396 | isl_space_free(model); |
397 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
398 | return NULL((void*)0); |
399 | } |
400 | |
401 | #undef TYPEisl_term |
402 | #define TYPEisl_term PWisl_pw_qpolynomial |
403 | |
404 | static |
405 | #include "isl_align_params_bin_templ.c" |
406 | |
407 | #undef SUFFIXset |
408 | #define SUFFIXset set |
409 | #undef ARG1isl_pw_qpolynomial |
410 | #define ARG1isl_pw_qpolynomial PWisl_pw_qpolynomial |
411 | #undef ARG2isl_map |
412 | #define ARG2isl_map isl_setisl_map |
413 | |
414 | static |
415 | #include "isl_align_params_templ.c" |
416 | |
417 | #undef TYPEisl_term |
418 | #define TYPEisl_term PWisl_pw_qpolynomial |
419 | |
420 | #include "isl_type_has_equal_space_bin_templ.c" |
421 | #include "isl_type_check_equal_space_templ.c" |
422 | |
423 | /* Private version of "union_add". For isl_pw_qpolynomial and |
424 | * isl_pw_qpolynomial_fold, we prefer to simply call it "add". |
425 | */ |
426 | static __isl_give PWisl_pw_qpolynomial *FN(PW,union_add_)isl_pw_qpolynomial_union_add_(__isl_take PWisl_pw_qpolynomial *pw1, __isl_take PWisl_pw_qpolynomial *pw2) |
427 | { |
428 | int i, j, n; |
429 | struct PWisl_pw_qpolynomial *res; |
430 | isl_ctx *ctx; |
431 | isl_setisl_map *set; |
432 | |
433 | if (FN(PW,align_params_bin)isl_pw_qpolynomial_align_params_bin(&pw1, &pw2) < 0) |
434 | goto error; |
435 | |
436 | ctx = isl_space_get_ctx(pw1->dim); |
437 | if (!OPT_EQUAL_TYPES(pw1->, pw2->)1) |
438 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 439); goto error; } while (0) |
439 | "fold types don't match", goto error)do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 439); goto error; } while (0); |
440 | if (FN(PW,check_equal_space)isl_pw_qpolynomial_check_equal_space(pw1, pw2) < 0) |
441 | goto error; |
442 | |
443 | if (FN(PW,IS_ZERO)isl_pw_qpolynomial_is_zero(pw1)) { |
444 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
445 | return pw2; |
446 | } |
447 | |
448 | if (FN(PW,IS_ZERO)isl_pw_qpolynomial_is_zero(pw2)) { |
449 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
450 | return pw1; |
451 | } |
452 | |
453 | n = (pw1->n + 1) * (pw2->n + 1); |
454 | res = FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(isl_space_copy(pw1->dim) |
455 | OPT_TYPE_ARG(pw1->), n); |
456 | |
457 | for (i = 0; i < pw1->n; ++i) { |
458 | set = isl_set_copy(pw1->p[i].set); |
459 | for (j = 0; j < pw2->n; ++j) { |
460 | struct isl_setisl_map *common; |
461 | ELisl_pw_qpolynomial *sum; |
462 | common = isl_set_intersect(isl_set_copy(pw1->p[i].set), |
463 | isl_set_copy(pw2->p[j].set)); |
464 | if (isl_set_plain_is_empty(common)) { |
465 | isl_set_free(common); |
466 | continue; |
467 | } |
468 | set = isl_set_subtract(set, |
469 | isl_set_copy(pw2->p[j].set)); |
470 | |
471 | sum = FN(EL,add_on_domain)isl_pw_qpolynomial_add_on_domain(common, |
472 | FN(EL,copy)isl_pw_qpolynomial_copy(pw1->p[i].FIELDqp), |
473 | FN(EL,copy)isl_pw_qpolynomial_copy(pw2->p[j].FIELDqp)); |
474 | |
475 | res = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(res, common, sum); |
476 | } |
477 | res = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(res, set, FN(EL,copy)isl_pw_qpolynomial_copy(pw1->p[i].FIELDqp)); |
478 | } |
479 | |
480 | for (j = 0; j < pw2->n; ++j) { |
481 | set = isl_set_copy(pw2->p[j].set); |
482 | for (i = 0; i < pw1->n; ++i) |
483 | set = isl_set_subtract(set, |
484 | isl_set_copy(pw1->p[i].set)); |
485 | res = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(res, set, FN(EL,copy)isl_pw_qpolynomial_copy(pw2->p[j].FIELDqp)); |
486 | } |
487 | |
488 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
489 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
490 | |
491 | return res; |
492 | error: |
493 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
494 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
495 | return NULL((void*)0); |
496 | } |
497 | |
498 | /* Make sure "pw" has room for at least "n" more pieces. |
499 | * |
500 | * If there is only one reference to pw, we extend it in place. |
501 | * Otherwise, we create a new PW and copy the pieces. |
502 | */ |
503 | static __isl_give PWisl_pw_qpolynomial *FN(PW,grow)isl_pw_qpolynomial_grow(__isl_take PWisl_pw_qpolynomial *pw, int n) |
504 | { |
505 | int i; |
506 | isl_ctx *ctx; |
507 | PWisl_pw_qpolynomial *res; |
508 | |
509 | if (!pw) |
510 | return NULL((void*)0); |
511 | if (pw->n + n <= pw->size) |
512 | return pw; |
513 | ctx = FN(PW,get_ctx)isl_pw_qpolynomial_get_ctx(pw); |
514 | n += pw->n; |
515 | if (pw->ref == 1) { |
516 | res = isl_realloc(ctx, pw, struct PW,((struct isl_pw_qpolynomial *)isl_realloc_or_die(ctx, pw, sizeof (struct isl_pw_qpolynomial) + (n - 1) * sizeof(struct isl_pw_qpolynomial_piece ))) |
517 | sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)))((struct isl_pw_qpolynomial *)isl_realloc_or_die(ctx, pw, sizeof (struct isl_pw_qpolynomial) + (n - 1) * sizeof(struct isl_pw_qpolynomial_piece ))); |
518 | if (!res) |
519 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
520 | res->size = n; |
521 | return res; |
522 | } |
523 | res = FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(isl_space_copy(pw->dim) OPT_TYPE_ARG(pw->), n); |
524 | if (!res) |
525 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
526 | for (i = 0; i < pw->n; ++i) |
527 | res = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(res, isl_set_copy(pw->p[i].set), |
528 | FN(EL,copy)isl_pw_qpolynomial_copy(pw->p[i].FIELDqp)); |
529 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
530 | return res; |
531 | } |
532 | |
533 | __isl_give PWisl_pw_qpolynomial *FN(PW,add_disjoint)isl_pw_qpolynomial_add_disjoint(__isl_take PWisl_pw_qpolynomial *pw1, __isl_take PWisl_pw_qpolynomial *pw2) |
534 | { |
535 | int i; |
536 | isl_ctx *ctx; |
537 | |
538 | if (FN(PW,align_params_bin)isl_pw_qpolynomial_align_params_bin(&pw1, &pw2) < 0) |
539 | goto error; |
540 | |
541 | if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n) |
542 | return FN(PW,add_disjoint)isl_pw_qpolynomial_add_disjoint(pw2, pw1); |
543 | |
544 | ctx = isl_space_get_ctx(pw1->dim); |
Value stored to 'ctx' is never read | |
545 | if (!OPT_EQUAL_TYPES(pw1->, pw2->)1) |
546 | isl_die(ctx, isl_error_invalid,do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 547); goto error; } while (0) |
547 | "fold types don't match", goto error)do { isl_handle_error(ctx, isl_error_invalid, "fold types don't match" , "polly/lib/External/isl/isl_pw_templ.c", 547); goto error; } while (0); |
548 | if (FN(PW,check_equal_space)isl_pw_qpolynomial_check_equal_space(pw1, pw2) < 0) |
549 | goto error; |
550 | |
551 | if (FN(PW,IS_ZERO)isl_pw_qpolynomial_is_zero(pw1)) { |
552 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
553 | return pw2; |
554 | } |
555 | |
556 | if (FN(PW,IS_ZERO)isl_pw_qpolynomial_is_zero(pw2)) { |
557 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
558 | return pw1; |
559 | } |
560 | |
561 | pw1 = FN(PW,grow)isl_pw_qpolynomial_grow(pw1, pw2->n); |
562 | if (!pw1) |
563 | goto error; |
564 | |
565 | for (i = 0; i < pw2->n; ++i) |
566 | pw1 = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(pw1, |
567 | isl_set_copy(pw2->p[i].set), |
568 | FN(EL,copy)isl_pw_qpolynomial_copy(pw2->p[i].FIELDqp)); |
569 | |
570 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
571 | |
572 | return pw1; |
573 | error: |
574 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
575 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
576 | return NULL((void*)0); |
577 | } |
578 | |
579 | /* This function is currently only used from isl_aff.c |
580 | */ |
581 | static __isl_give PWisl_pw_qpolynomial *FN(PW,on_shared_domain_in)isl_pw_qpolynomial_on_shared_domain_in(__isl_take PWisl_pw_qpolynomial *pw1, |
582 | __isl_take PWisl_pw_qpolynomial *pw2, __isl_take isl_space *space, |
583 | __isl_give ELisl_pw_qpolynomial *(*fn)(__isl_take ELisl_pw_qpolynomial *el1, __isl_take ELisl_pw_qpolynomial *el2)) |
584 | __attribute__ ((unused)); |
585 | |
586 | /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. |
587 | * The result of "fn" (and therefore also of this function) lives in "space". |
588 | */ |
589 | static __isl_give PWisl_pw_qpolynomial *FN(PW,on_shared_domain_in)isl_pw_qpolynomial_on_shared_domain_in(__isl_take PWisl_pw_qpolynomial *pw1, |
590 | __isl_take PWisl_pw_qpolynomial *pw2, __isl_take isl_space *space, |
591 | __isl_give ELisl_pw_qpolynomial *(*fn)(__isl_take ELisl_pw_qpolynomial *el1, __isl_take ELisl_pw_qpolynomial *el2)) |
592 | { |
593 | int i, j, n; |
594 | PWisl_pw_qpolynomial *res = NULL((void*)0); |
595 | |
596 | if (!pw1 || !pw2) |
597 | goto error; |
598 | |
599 | n = pw1->n * pw2->n; |
600 | res = FN(PW,alloc_size)isl_pw_qpolynomial_alloc_size(isl_space_copy(space) OPT_TYPE_ARG(pw1->), n); |
601 | |
602 | for (i = 0; i < pw1->n; ++i) { |
603 | for (j = 0; j < pw2->n; ++j) { |
604 | isl_setisl_map *common; |
605 | ELisl_pw_qpolynomial *res_ij; |
606 | int empty; |
607 | |
608 | common = isl_set_intersect( |
609 | isl_set_copy(pw1->p[i].set), |
610 | isl_set_copy(pw2->p[j].set)); |
611 | empty = isl_set_plain_is_empty(common); |
612 | if (empty < 0 || empty) { |
613 | isl_set_free(common); |
614 | if (empty < 0) |
615 | goto error; |
616 | continue; |
617 | } |
618 | |
619 | res_ij = fn(FN(EL,copy)isl_pw_qpolynomial_copy(pw1->p[i].FIELDqp), |
620 | FN(EL,copy)isl_pw_qpolynomial_copy(pw2->p[j].FIELDqp)); |
621 | res_ij = FN(EL,gist)isl_pw_qpolynomial_gist(res_ij, isl_set_copy(common)); |
622 | |
623 | res = FN(PW,add_piece)isl_pw_qpolynomial_add_piece(res, common, res_ij); |
624 | } |
625 | } |
626 | |
627 | isl_space_free(space); |
628 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
629 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
630 | return res; |
631 | error: |
632 | isl_space_free(space); |
633 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
634 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
635 | FN(PW,free)isl_pw_qpolynomial_free(res); |
636 | return NULL((void*)0); |
637 | } |
638 | |
639 | /* This function is currently only used from isl_aff.c |
640 | */ |
641 | static __isl_give PWisl_pw_qpolynomial *FN(PW,on_shared_domain)isl_pw_qpolynomial_on_shared_domain(__isl_take PWisl_pw_qpolynomial *pw1, |
642 | __isl_take PWisl_pw_qpolynomial *pw2, |
643 | __isl_give ELisl_pw_qpolynomial *(*fn)(__isl_take ELisl_pw_qpolynomial *el1, __isl_take ELisl_pw_qpolynomial *el2)) |
644 | __attribute__ ((unused)); |
645 | |
646 | /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. |
647 | * The result of "fn" is assumed to live in the same space as "pw1" and "pw2". |
648 | */ |
649 | static __isl_give PWisl_pw_qpolynomial *FN(PW,on_shared_domain)isl_pw_qpolynomial_on_shared_domain(__isl_take PWisl_pw_qpolynomial *pw1, |
650 | __isl_take PWisl_pw_qpolynomial *pw2, |
651 | __isl_give ELisl_pw_qpolynomial *(*fn)(__isl_take ELisl_pw_qpolynomial *el1, __isl_take ELisl_pw_qpolynomial *el2)) |
652 | { |
653 | isl_space *space; |
654 | |
655 | if (FN(PW,check_equal_space)isl_pw_qpolynomial_check_equal_space(pw1, pw2) < 0) |
656 | goto error; |
657 | |
658 | space = isl_space_copy(pw1->dim); |
659 | return FN(PW,on_shared_domain_in)isl_pw_qpolynomial_on_shared_domain_in(pw1, pw2, space, fn); |
660 | error: |
661 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
662 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
663 | return NULL((void*)0); |
664 | } |
665 | |
666 | /* Return the parameter domain of "pw". |
667 | */ |
668 | __isl_give isl_setisl_map *FN(PW,params)isl_pw_qpolynomial_params(__isl_take PWisl_pw_qpolynomial *pw) |
669 | { |
670 | return isl_set_params(FN(PW,domain)isl_pw_qpolynomial_domain(pw)); |
671 | } |
672 | |
673 | __isl_give isl_setisl_map *FN(PW,domain)isl_pw_qpolynomial_domain(__isl_take PWisl_pw_qpolynomial *pw) |
674 | { |
675 | int i; |
676 | isl_setisl_map *dom; |
677 | |
678 | if (!pw) |
679 | return NULL((void*)0); |
680 | |
681 | dom = isl_set_empty(FN(PW,get_domain_space)isl_pw_qpolynomial_get_domain_space(pw)); |
682 | for (i = 0; i < pw->n; ++i) |
683 | dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set)); |
684 | |
685 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
686 | |
687 | return dom; |
688 | } |
689 | |
690 | /* Exploit the equalities in the domain of piece "i" of "pw" |
691 | * to simplify the associated function. |
692 | * If the domain of piece "i" is empty, then remove it entirely, |
693 | * replacing it with the final piece. |
694 | */ |
695 | static int FN(PW,exploit_equalities_and_remove_if_empty)isl_pw_qpolynomial_exploit_equalities_and_remove_if_empty(__isl_keep PWisl_pw_qpolynomial *pw, |
696 | int i) |
697 | { |
698 | isl_basic_setisl_basic_map *aff; |
699 | int empty = isl_set_plain_is_empty(pw->p[i].set); |
700 | |
701 | if (empty < 0) |
702 | return -1; |
703 | if (empty) { |
704 | isl_set_free(pw->p[i].set); |
705 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[i].FIELDqp); |
706 | if (i != pw->n - 1) |
707 | pw->p[i] = pw->p[pw->n - 1]; |
708 | pw->n--; |
709 | |
710 | return 0; |
711 | } |
712 | |
713 | aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set)); |
714 | pw->p[i].FIELDqp = FN(EL,substitute_equalities)isl_pw_qpolynomial_substitute_equalities(pw->p[i].FIELDqp, aff); |
715 | if (!pw->p[i].FIELDqp) |
716 | return -1; |
717 | |
718 | return 0; |
719 | } |
720 | |
721 | /* Convert a piecewise expression defined over a parameter domain |
722 | * into one that is defined over a zero-dimensional set. |
723 | */ |
724 | __isl_give PWisl_pw_qpolynomial *FN(PW,from_range)isl_pw_qpolynomial_from_range(__isl_take PWisl_pw_qpolynomial *pw) |
725 | { |
726 | isl_space *space; |
727 | |
728 | if (!pw) |
729 | return NULL((void*)0); |
730 | if (!isl_space_is_set(pw->dim)) |
731 | isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "not living in a set space", "polly/lib/External/isl/isl_pw_templ.c" , 732); return isl_pw_qpolynomial_free(pw); } while (0) |
732 | "not living in a set space", return FN(PW,free)(pw))do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "not living in a set space", "polly/lib/External/isl/isl_pw_templ.c" , 732); return isl_pw_qpolynomial_free(pw); } while (0); |
733 | |
734 | space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
735 | space = isl_space_from_range(space); |
736 | pw = FN(PW,reset_space)isl_pw_qpolynomial_reset_space(pw, space); |
737 | |
738 | return pw; |
739 | } |
740 | |
741 | /* Fix the value of the given parameter or domain dimension of "pw" |
742 | * to be equal to "value". |
743 | */ |
744 | __isl_give PWisl_pw_qpolynomial *FN(PW,fix_si)isl_pw_qpolynomial_fix_si(__isl_take PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
745 | unsigned pos, int value) |
746 | { |
747 | int i; |
748 | |
749 | if (!pw) |
750 | return NULL((void*)0); |
751 | |
752 | if (type == isl_dim_out) |
753 | isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "cannot fix output dimension", "polly/lib/External/isl/isl_pw_templ.c" , 754); return isl_pw_qpolynomial_free(pw); } while (0) |
754 | "cannot fix output dimension", return FN(PW,free)(pw))do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "cannot fix output dimension", "polly/lib/External/isl/isl_pw_templ.c" , 754); return isl_pw_qpolynomial_free(pw); } while (0); |
755 | |
756 | if (pw->n == 0) |
757 | return pw; |
758 | |
759 | if (type == isl_dim_in) |
760 | type = isl_dim_set; |
761 | |
762 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
763 | if (!pw) |
764 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
765 | |
766 | for (i = pw->n - 1; i >= 0; --i) { |
767 | pw->p[i].set = isl_set_fix_si(pw->p[i].set, type, pos, value); |
768 | if (FN(PW,exploit_equalities_and_remove_if_empty)isl_pw_qpolynomial_exploit_equalities_and_remove_if_empty(pw, i) < 0) |
769 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
770 | } |
771 | |
772 | return pw; |
773 | } |
774 | |
775 | /* Restrict the domain of "pw" by combining each cell |
776 | * with "set" through a call to "fn", where "fn" may be |
777 | * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain, |
778 | * isl_set_intersect_factor_range or isl_set_subtract. |
779 | */ |
780 | static __isl_give PWisl_pw_qpolynomial *FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(__isl_take PWisl_pw_qpolynomial *pw, |
781 | __isl_take isl_setisl_map *set, |
782 | __isl_give isl_setisl_map *(*fn)(__isl_take isl_setisl_map *set1, |
783 | __isl_take isl_setisl_map *set2)) |
784 | { |
785 | int i; |
786 | |
787 | if (!pw || !set) |
788 | goto error; |
789 | |
790 | if (pw->n == 0) { |
791 | isl_set_free(set); |
792 | return pw; |
793 | } |
794 | |
795 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
796 | if (!pw) |
797 | goto error; |
798 | |
799 | for (i = pw->n - 1; i >= 0; --i) { |
800 | pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set)); |
801 | if (FN(PW,exploit_equalities_and_remove_if_empty)isl_pw_qpolynomial_exploit_equalities_and_remove_if_empty(pw, i) < 0) |
802 | goto error; |
803 | } |
804 | |
805 | isl_set_free(set); |
806 | return pw; |
807 | error: |
808 | isl_set_free(set); |
809 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
810 | return NULL((void*)0); |
811 | } |
812 | |
813 | __isl_give PWisl_pw_qpolynomial *FN(PW,intersect_domain)isl_pw_qpolynomial_intersect_domain(__isl_take PWisl_pw_qpolynomial *pw, |
814 | __isl_take isl_setisl_map *context) |
815 | { |
816 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &context); |
817 | return FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(pw, context, &isl_set_intersect); |
818 | } |
819 | |
820 | /* Intersect the domain of "pw" with the parameter domain "context". |
821 | */ |
822 | __isl_give PWisl_pw_qpolynomial *FN(PW,intersect_params)isl_pw_qpolynomial_intersect_params(__isl_take PWisl_pw_qpolynomial *pw, |
823 | __isl_take isl_setisl_map *context) |
824 | { |
825 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &context); |
826 | return FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(pw, context, |
827 | &isl_set_intersect_params); |
828 | } |
829 | |
830 | /* Given a piecewise expression "pw" with domain in a space [A -> B] and |
831 | * a set in the space A, intersect the domain with the set. |
832 | */ |
833 | __isl_give PWisl_pw_qpolynomial *FN(PW,intersect_domain_wrapped_domain)isl_pw_qpolynomial_intersect_domain_wrapped_domain(__isl_take PWisl_pw_qpolynomial *pw, |
834 | __isl_take isl_setisl_map *set) |
835 | { |
836 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &set); |
837 | return FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(pw, set, |
838 | &isl_set_intersect_factor_domain); |
839 | } |
840 | |
841 | /* Given a piecewise expression "pw" with domain in a space [A -> B] and |
842 | * a set in the space B, intersect the domain with the set. |
843 | */ |
844 | __isl_give PWisl_pw_qpolynomial *FN(PW,intersect_domain_wrapped_range)isl_pw_qpolynomial_intersect_domain_wrapped_range(__isl_take PWisl_pw_qpolynomial *pw, |
845 | __isl_take isl_setisl_map *set) |
846 | { |
847 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &set); |
848 | return FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(pw, set, |
849 | &isl_set_intersect_factor_range); |
850 | } |
851 | |
852 | /* Subtract "domain' from the domain of "pw". |
853 | */ |
854 | __isl_give PWisl_pw_qpolynomial *FN(PW,subtract_domain)isl_pw_qpolynomial_subtract_domain(__isl_take PWisl_pw_qpolynomial *pw, |
855 | __isl_take isl_setisl_map *domain) |
856 | { |
857 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &domain); |
858 | return FN(PW,restrict_domain_aligned)isl_pw_qpolynomial_restrict_domain_aligned(pw, domain, &isl_set_subtract); |
859 | } |
860 | |
861 | /* Compute the gist of "pw" with respect to the domain constraints |
862 | * of "context" for the case where the domain of the last element |
863 | * of "pw" is equal to "context". |
864 | * Call "fn_el" to compute the gist of this element, replace |
865 | * its domain by the universe and drop all other elements |
866 | * as their domains are necessarily disjoint from "context". |
867 | */ |
868 | static __isl_give PWisl_pw_qpolynomial *FN(PW,gist_last)isl_pw_qpolynomial_gist_last(__isl_take PWisl_pw_qpolynomial *pw, |
869 | __isl_take isl_setisl_map *context, |
870 | __isl_give ELisl_pw_qpolynomial *(*fn_el)(__isl_take ELisl_pw_qpolynomial *el, __isl_take isl_setisl_map *set)) |
871 | { |
872 | int i; |
873 | isl_space *space; |
874 | |
875 | for (i = 0; i < pw->n - 1; ++i) { |
876 | isl_set_free(pw->p[i].set); |
877 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[i].FIELDqp); |
878 | } |
879 | pw->p[0].FIELDqp = pw->p[pw->n - 1].FIELDqp; |
880 | pw->p[0].set = pw->p[pw->n - 1].set; |
881 | pw->n = 1; |
882 | |
883 | space = isl_set_get_space(context); |
884 | pw->p[0].FIELDqp = fn_el(pw->p[0].FIELDqp, context); |
885 | context = isl_set_universe(space); |
886 | isl_set_free(pw->p[0].set); |
887 | pw->p[0].set = context; |
888 | |
889 | if (!pw->p[0].FIELDqp || !pw->p[0].set) |
890 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
891 | |
892 | return pw; |
893 | } |
894 | |
895 | /* Compute the gist of "pw" with respect to the domain constraints |
896 | * of "context". Call "fn_el" to compute the gist of the elements |
897 | * and "fn_dom" to compute the gist of the domains. |
898 | * |
899 | * If the piecewise expression is empty or the context is the universe, |
900 | * then nothing can be simplified. |
901 | */ |
902 | static __isl_give PWisl_pw_qpolynomial *FN(PW,gist_aligned)isl_pw_qpolynomial_gist_aligned(__isl_take PWisl_pw_qpolynomial *pw, |
903 | __isl_take isl_setisl_map *context, |
904 | __isl_give ELisl_pw_qpolynomial *(*fn_el)(__isl_take ELisl_pw_qpolynomial *el, |
905 | __isl_take isl_setisl_map *set), |
906 | __isl_give isl_setisl_map *(*fn_dom)(__isl_take isl_setisl_map *set, |
907 | __isl_take isl_basic_setisl_basic_map *bset)) |
908 | { |
909 | int i; |
910 | int is_universe; |
911 | isl_bool aligned; |
912 | isl_basic_setisl_basic_map *hull = NULL((void*)0); |
913 | |
914 | if (!pw || !context) |
915 | goto error; |
916 | |
917 | if (pw->n == 0) { |
918 | isl_set_free(context); |
919 | return pw; |
920 | } |
921 | |
922 | is_universe = isl_set_plain_is_universe(context); |
923 | if (is_universe < 0) |
924 | goto error; |
925 | if (is_universe) { |
926 | isl_set_free(context); |
927 | return pw; |
928 | } |
929 | |
930 | aligned = isl_set_space_has_equal_params(context, pw->dim); |
931 | if (aligned < 0) |
932 | goto error; |
933 | if (!aligned) { |
934 | pw = FN(PW,align_params)isl_pw_qpolynomial_align_params(pw, isl_set_get_space(context)); |
935 | context = isl_set_align_params(context, FN(PW,get_space)isl_pw_qpolynomial_get_space(pw)); |
936 | } |
937 | |
938 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
939 | if (!pw) |
940 | goto error; |
941 | |
942 | if (pw->n == 1) { |
943 | int equal; |
944 | |
945 | equal = isl_set_plain_is_equal(pw->p[0].set, context); |
946 | if (equal < 0) |
947 | goto error; |
948 | if (equal) |
949 | return FN(PW,gist_last)isl_pw_qpolynomial_gist_last(pw, context, fn_el); |
950 | } |
951 | |
952 | context = isl_set_compute_divs(context); |
953 | hull = isl_set_simple_hull(isl_set_copy(context)); |
954 | |
955 | for (i = pw->n - 1; i >= 0; --i) { |
956 | isl_setisl_map *set_i; |
957 | int empty; |
958 | |
959 | if (i == pw->n - 1) { |
960 | int equal; |
961 | equal = isl_set_plain_is_equal(pw->p[i].set, context); |
962 | if (equal < 0) |
963 | goto error; |
964 | if (equal) { |
965 | isl_basic_set_free(hull); |
966 | return FN(PW,gist_last)isl_pw_qpolynomial_gist_last(pw, context, fn_el); |
967 | } |
968 | } |
969 | set_i = isl_set_intersect(isl_set_copy(pw->p[i].set), |
970 | isl_set_copy(context)); |
971 | empty = isl_set_plain_is_empty(set_i); |
972 | pw->p[i].FIELDqp = fn_el(pw->p[i].FIELDqp, set_i); |
973 | pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull)); |
974 | if (empty < 0 || !pw->p[i].FIELDqp || !pw->p[i].set) |
975 | goto error; |
976 | if (empty) { |
977 | isl_set_free(pw->p[i].set); |
978 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[i].FIELDqp); |
979 | if (i != pw->n - 1) |
980 | pw->p[i] = pw->p[pw->n - 1]; |
981 | pw->n--; |
982 | } |
983 | } |
984 | |
985 | isl_basic_set_free(hull); |
986 | isl_set_free(context); |
987 | |
988 | return pw; |
989 | error: |
990 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
991 | isl_basic_set_free(hull); |
992 | isl_set_free(context); |
993 | return NULL((void*)0); |
994 | } |
995 | |
996 | __isl_give PWisl_pw_qpolynomial *FN(PW,gist)isl_pw_qpolynomial_gist(__isl_take PWisl_pw_qpolynomial *pw, __isl_take isl_setisl_map *context) |
997 | { |
998 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &context); |
999 | return FN(PW,gist_aligned)isl_pw_qpolynomial_gist_aligned(pw, context, &FN(EL,gist)isl_pw_qpolynomial_gist, |
1000 | &isl_set_gist_basic_set); |
1001 | } |
1002 | |
1003 | __isl_give PWisl_pw_qpolynomial *FN(PW,gist_params)isl_pw_qpolynomial_gist_params(__isl_take PWisl_pw_qpolynomial *pw, |
1004 | __isl_take isl_setisl_map *context) |
1005 | { |
1006 | FN(PW,align_params_set)isl_pw_qpolynomial_align_params_set(&pw, &context); |
1007 | return FN(PW,gist_aligned)isl_pw_qpolynomial_gist_aligned(pw, context, &FN(EL,gist_params)isl_pw_qpolynomial_gist_params, |
1008 | &isl_set_gist_params_basic_set); |
1009 | } |
1010 | |
1011 | /* Return -1 if the piece "p1" should be sorted before "p2" |
1012 | * and 1 if it should be sorted after "p2". |
1013 | * Return 0 if they do not need to be sorted in a specific order. |
1014 | * |
1015 | * The two pieces are compared on the basis of their function value expressions. |
1016 | */ |
1017 | static int FN(PW,sort_field_cmp)isl_pw_qpolynomial_sort_field_cmp(const void *p1, const void *p2, void *arg) |
1018 | { |
1019 | struct FN(PW,piece)isl_pw_qpolynomial_piece const *pc1 = p1; |
1020 | struct FN(PW,piece)isl_pw_qpolynomial_piece const *pc2 = p2; |
1021 | |
1022 | return FN(EL,plain_cmp)isl_pw_qpolynomial_plain_cmp(pc1->FIELDqp, pc2->FIELDqp); |
1023 | } |
1024 | |
1025 | /* Sort the pieces of "pw" according to their function value |
1026 | * expressions and then combine pairs of adjacent pieces with |
1027 | * the same such expression. |
1028 | * |
1029 | * The sorting is performed in place because it does not |
1030 | * change the meaning of "pw", but care needs to be |
1031 | * taken not to change any possible other copies of "pw" |
1032 | * in case anything goes wrong. |
1033 | */ |
1034 | __isl_give PWisl_pw_qpolynomial *FN(PW,sort)isl_pw_qpolynomial_sort(__isl_take PWisl_pw_qpolynomial *pw) |
1035 | { |
1036 | int i, j; |
1037 | isl_setisl_map *set; |
1038 | |
1039 | if (!pw) |
1040 | return NULL((void*)0); |
1041 | if (pw->n <= 1) |
1042 | return pw; |
1043 | if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]), |
1044 | &FN(PW,sort_field_cmp)isl_pw_qpolynomial_sort_field_cmp, NULL((void*)0)) < 0) |
1045 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1046 | for (i = pw->n - 1; i >= 1; --i) { |
1047 | if (!FN(EL,plain_is_equal)isl_pw_qpolynomial_plain_is_equal(pw->p[i - 1].FIELDqp, pw->p[i].FIELDqp)) |
1048 | continue; |
1049 | set = isl_set_union(isl_set_copy(pw->p[i - 1].set), |
1050 | isl_set_copy(pw->p[i].set)); |
1051 | if (!set) |
1052 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1053 | isl_set_free(pw->p[i].set); |
1054 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[i].FIELDqp); |
1055 | isl_set_free(pw->p[i - 1].set); |
1056 | pw->p[i - 1].set = set; |
1057 | for (j = i + 1; j < pw->n; ++j) |
1058 | pw->p[j - 1] = pw->p[j]; |
1059 | pw->n--; |
1060 | } |
1061 | |
1062 | return pw; |
1063 | } |
1064 | |
1065 | /* Coalesce the domains of "pw". |
1066 | * |
1067 | * Prior to the actual coalescing, first sort the pieces such that |
1068 | * pieces with the same function value expression are combined |
1069 | * into a single piece, the combined domain of which can then |
1070 | * be coalesced. |
1071 | */ |
1072 | __isl_give PWisl_pw_qpolynomial *FN(PW,coalesce)isl_pw_qpolynomial_coalesce(__isl_take PWisl_pw_qpolynomial *pw) |
1073 | { |
1074 | int i; |
1075 | |
1076 | pw = FN(PW,sort)isl_pw_qpolynomial_sort(pw); |
1077 | if (!pw) |
1078 | return NULL((void*)0); |
1079 | |
1080 | for (i = 0; i < pw->n; ++i) { |
1081 | pw->p[i].set = isl_set_coalesce(pw->p[i].set); |
1082 | if (!pw->p[i].set) |
1083 | goto error; |
1084 | } |
1085 | |
1086 | return pw; |
1087 | error: |
1088 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1089 | return NULL((void*)0); |
1090 | } |
1091 | |
1092 | isl_ctx *FN(PW,get_ctx)isl_pw_qpolynomial_get_ctx(__isl_keep PWisl_pw_qpolynomial *pw) |
1093 | { |
1094 | return pw ? isl_space_get_ctx(pw->dim) : NULL((void*)0); |
1095 | } |
1096 | |
1097 | isl_bool FN(PW,involves_dims)isl_pw_qpolynomial_involves_dims(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
1098 | unsigned first, unsigned n) |
1099 | { |
1100 | int i; |
1101 | enum isl_dim_type set_type; |
1102 | |
1103 | if (!pw) |
1104 | return isl_bool_error; |
1105 | if (pw->n == 0 || n == 0) |
1106 | return isl_bool_false; |
1107 | |
1108 | set_type = type == isl_dim_in ? isl_dim_set : type; |
1109 | |
1110 | for (i = 0; i < pw->n; ++i) { |
1111 | isl_bool involves = FN(EL,involves_dims)isl_pw_qpolynomial_involves_dims(pw->p[i].FIELDqp, |
1112 | type, first, n); |
1113 | if (involves < 0 || involves) |
1114 | return involves; |
1115 | involves = isl_set_involves_dims(pw->p[i].set, |
1116 | set_type, first, n); |
1117 | if (involves < 0 || involves) |
1118 | return involves; |
1119 | } |
1120 | return isl_bool_false; |
1121 | } |
1122 | |
1123 | __isl_give PWisl_pw_qpolynomial *FN(PW,set_dim_name)isl_pw_qpolynomial_set_dim_name(__isl_take PWisl_pw_qpolynomial *pw, |
1124 | enum isl_dim_type type, unsigned pos, const char *s) |
1125 | { |
1126 | int i; |
1127 | enum isl_dim_type set_type; |
1128 | |
1129 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1130 | if (!pw) |
1131 | return NULL((void*)0); |
1132 | |
1133 | set_type = type == isl_dim_in ? isl_dim_set : type; |
1134 | |
1135 | pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s); |
1136 | if (!pw->dim) |
1137 | goto error; |
1138 | |
1139 | for (i = 0; i < pw->n; ++i) { |
1140 | pw->p[i].set = isl_set_set_dim_name(pw->p[i].set, |
1141 | set_type, pos, s); |
1142 | if (!pw->p[i].set) |
1143 | goto error; |
1144 | pw->p[i].FIELDqp = FN(EL,set_dim_name)isl_pw_qpolynomial_set_dim_name(pw->p[i].FIELDqp, type, pos, s); |
1145 | if (!pw->p[i].FIELDqp) |
1146 | goto error; |
1147 | } |
1148 | |
1149 | return pw; |
1150 | error: |
1151 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1152 | return NULL((void*)0); |
1153 | } |
1154 | |
1155 | __isl_give PWisl_pw_qpolynomial *FN(PW,drop_dims)isl_pw_qpolynomial_drop_dims(__isl_take PWisl_pw_qpolynomial *pw, |
1156 | enum isl_dim_type type, unsigned first, unsigned n) |
1157 | { |
1158 | int i; |
1159 | enum isl_dim_type set_type; |
1160 | |
1161 | if (!pw) |
1162 | return NULL((void*)0); |
1163 | if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) |
1164 | return pw; |
1165 | |
1166 | set_type = type == isl_dim_in ? isl_dim_set : type; |
1167 | |
1168 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1169 | if (!pw) |
1170 | return NULL((void*)0); |
1171 | pw->dim = isl_space_drop_dims(pw->dim, type, first, n); |
1172 | if (!pw->dim) |
1173 | goto error; |
1174 | for (i = 0; i < pw->n; ++i) { |
1175 | pw->p[i].FIELDqp = FN(EL,drop_dims)isl_pw_qpolynomial_drop_dims(pw->p[i].FIELDqp, type, first, n); |
1176 | if (!pw->p[i].FIELDqp) |
1177 | goto error; |
1178 | if (type == isl_dim_out) |
1179 | continue; |
1180 | pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n); |
1181 | if (!pw->p[i].set) |
1182 | goto error; |
1183 | } |
1184 | |
1185 | return pw; |
1186 | error: |
1187 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1188 | return NULL((void*)0); |
1189 | } |
1190 | |
1191 | /* This function is very similar to drop_dims. |
1192 | * The only difference is that the cells may still involve |
1193 | * the specified dimensions. They are removed using |
1194 | * isl_set_project_out instead of isl_set_drop. |
1195 | */ |
1196 | __isl_give PWisl_pw_qpolynomial *FN(PW,project_out)isl_pw_qpolynomial_project_out(__isl_take PWisl_pw_qpolynomial *pw, |
1197 | enum isl_dim_type type, unsigned first, unsigned n) |
1198 | { |
1199 | int i; |
1200 | enum isl_dim_type set_type; |
1201 | |
1202 | if (!pw) |
1203 | return NULL((void*)0); |
1204 | if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) |
1205 | return pw; |
1206 | |
1207 | set_type = type == isl_dim_in ? isl_dim_set : type; |
1208 | |
1209 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1210 | if (!pw) |
1211 | return NULL((void*)0); |
1212 | pw->dim = isl_space_drop_dims(pw->dim, type, first, n); |
1213 | if (!pw->dim) |
1214 | goto error; |
1215 | for (i = 0; i < pw->n; ++i) { |
1216 | pw->p[i].set = isl_set_project_out(pw->p[i].set, |
1217 | set_type, first, n); |
1218 | if (!pw->p[i].set) |
1219 | goto error; |
1220 | pw->p[i].FIELDqp = FN(EL,drop_dims)isl_pw_qpolynomial_drop_dims(pw->p[i].FIELDqp, type, first, n); |
1221 | if (!pw->p[i].FIELDqp) |
1222 | goto error; |
1223 | } |
1224 | |
1225 | return pw; |
1226 | error: |
1227 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1228 | return NULL((void*)0); |
1229 | } |
1230 | |
1231 | /* Project the domain of pw onto its parameter space. |
1232 | */ |
1233 | __isl_give PWisl_pw_qpolynomial *FN(PW,project_domain_on_params)isl_pw_qpolynomial_project_domain_on_params(__isl_take PWisl_pw_qpolynomial *pw) |
1234 | { |
1235 | isl_space *space; |
1236 | isl_size n; |
1237 | |
1238 | n = FN(PW,dim)isl_pw_qpolynomial_dim(pw, isl_dim_in); |
1239 | if (n < 0) |
1240 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1241 | pw = FN(PW,project_out)isl_pw_qpolynomial_project_out(pw, isl_dim_in, 0, n); |
1242 | space = FN(PW,get_domain_space)isl_pw_qpolynomial_get_domain_space(pw); |
1243 | space = isl_space_params(space); |
1244 | pw = FN(PW,reset_domain_space)isl_pw_qpolynomial_reset_domain_space(pw, space); |
1245 | return pw; |
1246 | } |
1247 | |
1248 | /* Drop all parameters not referenced by "pw". |
1249 | */ |
1250 | __isl_give PWisl_pw_qpolynomial *FN(PW,drop_unused_params)isl_pw_qpolynomial_drop_unused_params(__isl_take PWisl_pw_qpolynomial *pw) |
1251 | { |
1252 | isl_size n; |
1253 | int i; |
1254 | |
1255 | if (FN(PW,check_named_params)isl_pw_qpolynomial_check_named_params(pw) < 0) |
1256 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1257 | |
1258 | n = FN(PW,dim)isl_pw_qpolynomial_dim(pw, isl_dim_param); |
1259 | if (n < 0) |
1260 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1261 | for (i = n - 1; i >= 0; i--) { |
1262 | isl_bool involves; |
1263 | |
1264 | involves = FN(PW,involves_dims)isl_pw_qpolynomial_involves_dims(pw, isl_dim_param, i, 1); |
1265 | if (involves < 0) |
1266 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1267 | if (!involves) |
1268 | pw = FN(PW,drop_dims)isl_pw_qpolynomial_drop_dims(pw, isl_dim_param, i, 1); |
1269 | } |
1270 | |
1271 | return pw; |
1272 | } |
1273 | |
1274 | __isl_give PWisl_pw_qpolynomial *FN(PW,fix_dim)isl_pw_qpolynomial_fix_dim(__isl_take PWisl_pw_qpolynomial *pw, |
1275 | enum isl_dim_type type, unsigned pos, isl_int v) |
1276 | { |
1277 | int i; |
1278 | |
1279 | if (!pw) |
1280 | return NULL((void*)0); |
1281 | |
1282 | if (type == isl_dim_in) |
1283 | type = isl_dim_set; |
1284 | |
1285 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1286 | if (!pw) |
1287 | return NULL((void*)0); |
1288 | for (i = 0; i < pw->n; ++i) { |
1289 | pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v); |
1290 | if (FN(PW,exploit_equalities_and_remove_if_empty)isl_pw_qpolynomial_exploit_equalities_and_remove_if_empty(pw, i) < 0) |
1291 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1292 | } |
1293 | |
1294 | return pw; |
1295 | } |
1296 | |
1297 | /* Fix the value of the variable at position "pos" of type "type" of "pw" |
1298 | * to be equal to "v". |
1299 | */ |
1300 | __isl_give PWisl_pw_qpolynomial *FN(PW,fix_val)isl_pw_qpolynomial_fix_val(__isl_take PWisl_pw_qpolynomial *pw, |
1301 | enum isl_dim_type type, unsigned pos, __isl_take isl_val *v) |
1302 | { |
1303 | if (!v) |
1304 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1305 | if (!isl_val_is_int(v)) |
1306 | isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "expecting integer value", "polly/lib/External/isl/isl_pw_templ.c" , 1307); goto error; } while (0) |
1307 | "expecting integer value", goto error)do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "expecting integer value", "polly/lib/External/isl/isl_pw_templ.c" , 1307); goto error; } while (0); |
1308 | |
1309 | pw = FN(PW,fix_dim)isl_pw_qpolynomial_fix_dim(pw, type, pos, v->n); |
1310 | isl_val_free(v); |
1311 | |
1312 | return pw; |
1313 | error: |
1314 | isl_val_free(v); |
1315 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1316 | } |
1317 | |
1318 | isl_size FN(PW,dim)isl_pw_qpolynomial_dim(__isl_keep PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
1319 | { |
1320 | return isl_space_dim(FN(PW,peek_space)isl_pw_qpolynomial_peek_space(pw), type); |
1321 | } |
1322 | |
1323 | __isl_give PWisl_pw_qpolynomial *FN(PW,split_dims)isl_pw_qpolynomial_split_dims(__isl_take PWisl_pw_qpolynomial *pw, |
1324 | enum isl_dim_type type, unsigned first, unsigned n) |
1325 | { |
1326 | int i; |
1327 | |
1328 | if (!pw) |
1329 | return NULL((void*)0); |
1330 | if (n == 0) |
1331 | return pw; |
1332 | |
1333 | if (type == isl_dim_in) |
1334 | type = isl_dim_set; |
1335 | |
1336 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1337 | if (!pw) |
1338 | return NULL((void*)0); |
1339 | if (!pw->dim) |
1340 | goto error; |
1341 | for (i = 0; i < pw->n; ++i) { |
1342 | pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n); |
1343 | if (!pw->p[i].set) |
1344 | goto error; |
1345 | } |
1346 | |
1347 | return pw; |
1348 | error: |
1349 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1350 | return NULL((void*)0); |
1351 | } |
1352 | |
1353 | /* Return the space of "pw". |
1354 | */ |
1355 | __isl_keep isl_space *FN(PW,peek_space)isl_pw_qpolynomial_peek_space(__isl_keep PWisl_pw_qpolynomial *pw) |
1356 | { |
1357 | return pw ? pw->dim : NULL((void*)0); |
1358 | } |
1359 | |
1360 | __isl_give isl_space *FN(PW,get_space)isl_pw_qpolynomial_get_space(__isl_keep PWisl_pw_qpolynomial *pw) |
1361 | { |
1362 | return isl_space_copy(FN(PW,peek_space)isl_pw_qpolynomial_peek_space(pw)); |
1363 | } |
1364 | |
1365 | /* Return the space of "pw". |
1366 | * This may be either a copy or the space itself |
1367 | * if there is only one reference to "pw". |
1368 | * This allows the space to be modified inplace |
1369 | * if both the piecewise expression and its space have only a single reference. |
1370 | * The caller is not allowed to modify "pw" between this call and |
1371 | * a subsequent call to isl_pw_*_restore_*. |
1372 | * The only exception is that isl_pw_*_free can be called instead. |
1373 | */ |
1374 | __isl_give isl_space *FN(PW,take_space)isl_pw_qpolynomial_take_space(__isl_keep PWisl_pw_qpolynomial *pw) |
1375 | { |
1376 | isl_space *space; |
1377 | |
1378 | if (!pw) |
1379 | return NULL((void*)0); |
1380 | if (pw->ref != 1) |
1381 | return FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1382 | space = pw->dim; |
1383 | pw->dim = NULL((void*)0); |
1384 | return space; |
1385 | } |
1386 | |
1387 | /* Set the space of "pw" to "space", where the space of "pw" may be missing |
1388 | * due to a preceding call to isl_pw_*_take_space. |
1389 | * However, in this case, "pw" only has a single reference and |
1390 | * then the call to isl_pw_*_cow has no effect. |
1391 | */ |
1392 | __isl_give PWisl_pw_qpolynomial *FN(PW,restore_space)isl_pw_qpolynomial_restore_space(__isl_take PWisl_pw_qpolynomial *pw, |
1393 | __isl_take isl_space *space) |
1394 | { |
1395 | if (!pw || !space) |
1396 | goto error; |
1397 | |
1398 | if (pw->dim == space) { |
1399 | isl_space_free(space); |
1400 | return pw; |
1401 | } |
1402 | |
1403 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1404 | if (!pw) |
1405 | goto error; |
1406 | isl_space_free(pw->dim); |
1407 | pw->dim = space; |
1408 | |
1409 | return pw; |
1410 | error: |
1411 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1412 | isl_space_free(space); |
1413 | return NULL((void*)0); |
1414 | } |
1415 | |
1416 | /* Check that "pos" is a valid position for a cell in "pw". |
1417 | */ |
1418 | static isl_stat FN(PW,check_pos)isl_pw_qpolynomial_check_pos(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1419 | { |
1420 | if (!pw) |
1421 | return isl_stat_error; |
1422 | if (pos < 0 || pos >= pw->n) |
1423 | isl_die(FN(PW,get_ctx)(pw), isl_error_internal,do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_internal , "position out of bounds", "polly/lib/External/isl/isl_pw_templ.c" , 1424); return isl_stat_error; } while (0) |
1424 | "position out of bounds", return isl_stat_error)do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_internal , "position out of bounds", "polly/lib/External/isl/isl_pw_templ.c" , 1424); return isl_stat_error; } while (0); |
1425 | return isl_stat_ok; |
1426 | } |
1427 | |
1428 | /* Return the cell at position "pos" in "pw". |
1429 | */ |
1430 | static __isl_keep isl_setisl_map *FN(PW,peek_domain_at)isl_pw_qpolynomial_peek_domain_at(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1431 | { |
1432 | if (FN(PW,check_pos)isl_pw_qpolynomial_check_pos(pw, pos) < 0) |
1433 | return NULL((void*)0); |
1434 | return pw->p[pos].set; |
1435 | } |
1436 | |
1437 | /* Return a copy of the cell at position "pos" in "pw". |
1438 | */ |
1439 | __isl_give isl_setisl_map *FN(PW,get_domain_at)isl_pw_qpolynomial_get_domain_at(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1440 | { |
1441 | return isl_set_copy(FN(PW,peek_domain_at)isl_pw_qpolynomial_peek_domain_at(pw, pos)); |
1442 | } |
1443 | |
1444 | /* Return the base expression associated to |
1445 | * the cell at position "pos" in "pw". |
1446 | */ |
1447 | static __isl_keep ELisl_pw_qpolynomial *FN(PW,peek_base_at)isl_pw_qpolynomial_peek_base_at(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1448 | { |
1449 | if (FN(PW,check_pos)isl_pw_qpolynomial_check_pos(pw, pos) < 0) |
1450 | return NULL((void*)0); |
1451 | return pw->p[pos].FIELDqp; |
1452 | } |
1453 | |
1454 | /* Return a copy of the base expression associated to |
1455 | * the cell at position "pos" in "pw". |
1456 | */ |
1457 | __isl_give ELisl_pw_qpolynomial *FN(PW,get_base_at)isl_pw_qpolynomial_get_base_at(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1458 | { |
1459 | return FN(EL,copy)isl_pw_qpolynomial_copy(FN(PW,peek_base_at)isl_pw_qpolynomial_peek_base_at(pw, pos)); |
1460 | } |
1461 | |
1462 | /* Return the base expression associated to |
1463 | * the cell at position "pos" in "pw". |
1464 | * This may be either a copy or the base expression itself |
1465 | * if there is only one reference to "pw". |
1466 | * This allows the base expression to be modified inplace |
1467 | * if both the piecewise expression and this base expression |
1468 | * have only a single reference. |
1469 | * The caller is not allowed to modify "pw" between this call and |
1470 | * a subsequent call to isl_pw_*_restore_*. |
1471 | * The only exception is that isl_pw_*_free can be called instead. |
1472 | */ |
1473 | __isl_give ELisl_pw_qpolynomial *FN(PW,take_base_at)isl_pw_qpolynomial_take_base_at(__isl_keep PWisl_pw_qpolynomial *pw, int pos) |
1474 | { |
1475 | ELisl_pw_qpolynomial *el; |
1476 | |
1477 | if (!pw) |
1478 | return NULL((void*)0); |
1479 | if (pw->ref != 1) |
1480 | return FN(PW,get_base_at)isl_pw_qpolynomial_get_base_at(pw, pos); |
1481 | if (FN(PW,check_pos)isl_pw_qpolynomial_check_pos(pw, pos) < 0) |
1482 | return NULL((void*)0); |
1483 | el = pw->p[pos].FIELDqp; |
1484 | pw->p[pos].FIELDqp = NULL((void*)0); |
1485 | return el; |
1486 | } |
1487 | |
1488 | /* Set the base expression associated to |
1489 | * the cell at position "pos" in "pw" to "el", |
1490 | * where this base expression may be missing |
1491 | * due to a preceding call to isl_pw_*_take_base_at. |
1492 | * However, in this case, "pw" only has a single reference and |
1493 | * then the call to isl_pw_*_cow has no effect. |
1494 | */ |
1495 | __isl_give PWisl_pw_qpolynomial *FN(PW,restore_base_at)isl_pw_qpolynomial_restore_base_at(__isl_take PWisl_pw_qpolynomial *pw, int pos, |
1496 | __isl_take ELisl_pw_qpolynomial *el) |
1497 | { |
1498 | if (FN(PW,check_pos)isl_pw_qpolynomial_check_pos(pw, pos) < 0 || !el) |
1499 | goto error; |
1500 | |
1501 | if (pw->p[pos].FIELDqp == el) { |
1502 | FN(EL,free)isl_pw_qpolynomial_free(el); |
1503 | return pw; |
1504 | } |
1505 | |
1506 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1507 | if (!pw) |
1508 | goto error; |
1509 | FN(EL,free)isl_pw_qpolynomial_free(pw->p[pos].FIELDqp); |
1510 | pw->p[pos].FIELDqp = el; |
1511 | |
1512 | return pw; |
1513 | error: |
1514 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1515 | FN(EL,free)isl_pw_qpolynomial_free(el); |
1516 | return NULL((void*)0); |
1517 | } |
1518 | |
1519 | __isl_give isl_space *FN(PW,get_domain_space)isl_pw_qpolynomial_get_domain_space(__isl_keep PWisl_pw_qpolynomial *pw) |
1520 | { |
1521 | return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL((void*)0); |
1522 | } |
1523 | |
1524 | /* Return the position of the dimension of the given type and name |
1525 | * in "pw". |
1526 | * Return -1 if no such dimension can be found. |
1527 | */ |
1528 | int FN(PW,find_dim_by_name)isl_pw_qpolynomial_find_dim_by_name(__isl_keep PWisl_pw_qpolynomial *pw, |
1529 | enum isl_dim_type type, const char *name) |
1530 | { |
1531 | if (!pw) |
1532 | return -1; |
1533 | return isl_space_find_dim_by_name(pw->dim, type, name); |
1534 | } |
1535 | |
1536 | /* Return the position of the dimension of the given type and identifier |
1537 | * in "pw". |
1538 | * Return -1 if no such dimension can be found. |
1539 | */ |
1540 | static int FN(PW,find_dim_by_id)isl_pw_qpolynomial_find_dim_by_id(__isl_keep PWisl_pw_qpolynomial *pw, |
1541 | enum isl_dim_type type, __isl_keep isl_id *id) |
1542 | { |
1543 | isl_space *space; |
1544 | |
1545 | space = FN(PW,peek_space)isl_pw_qpolynomial_peek_space(pw); |
1546 | return isl_space_find_dim_by_id(space, type, id); |
1547 | } |
1548 | |
1549 | /* Does the piecewise expression "pw" depend in any way |
1550 | * on the parameter with identifier "id"? |
1551 | */ |
1552 | isl_bool FN(PW,involves_param_id)isl_pw_qpolynomial_involves_param_id(__isl_keep PWisl_pw_qpolynomial *pw, __isl_keep isl_id *id) |
1553 | { |
1554 | int pos; |
1555 | |
1556 | if (!pw || !id) |
1557 | return isl_bool_error; |
1558 | if (pw->n == 0) |
1559 | return isl_bool_false; |
1560 | |
1561 | pos = FN(PW,find_dim_by_id)isl_pw_qpolynomial_find_dim_by_id(pw, isl_dim_param, id); |
1562 | if (pos < 0) |
1563 | return isl_bool_false; |
1564 | return FN(PW,involves_dims)isl_pw_qpolynomial_involves_dims(pw, isl_dim_param, pos, 1); |
1565 | } |
1566 | |
1567 | /* Reset the space of "pw". Since we don't know if the elements |
1568 | * represent the spaces themselves or their domains, we pass along |
1569 | * both when we call their reset_space_and_domain. |
1570 | */ |
1571 | static __isl_give PWisl_pw_qpolynomial *FN(PW,reset_space_and_domain)isl_pw_qpolynomial_reset_space_and_domain(__isl_take PWisl_pw_qpolynomial *pw, |
1572 | __isl_take isl_space *space, __isl_take isl_space *domain) |
1573 | { |
1574 | int i; |
1575 | |
1576 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1577 | if (!pw || !space || !domain) |
1578 | goto error; |
1579 | |
1580 | for (i = 0; i < pw->n; ++i) { |
1581 | pw->p[i].set = isl_set_reset_space(pw->p[i].set, |
1582 | isl_space_copy(domain)); |
1583 | if (!pw->p[i].set) |
1584 | goto error; |
1585 | pw->p[i].FIELDqp = FN(EL,reset_space_and_domain)isl_pw_qpolynomial_reset_space_and_domain(pw->p[i].FIELDqp, |
1586 | isl_space_copy(space), isl_space_copy(domain)); |
1587 | if (!pw->p[i].FIELDqp) |
1588 | goto error; |
1589 | } |
1590 | |
1591 | isl_space_free(domain); |
1592 | |
1593 | isl_space_free(pw->dim); |
1594 | pw->dim = space; |
1595 | |
1596 | return pw; |
1597 | error: |
1598 | isl_space_free(domain); |
1599 | isl_space_free(space); |
1600 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1601 | return NULL((void*)0); |
1602 | } |
1603 | |
1604 | __isl_give PWisl_pw_qpolynomial *FN(PW,reset_domain_space)isl_pw_qpolynomial_reset_domain_space(__isl_take PWisl_pw_qpolynomial *pw, |
1605 | __isl_take isl_space *domain) |
1606 | { |
1607 | isl_space *space; |
1608 | |
1609 | space = isl_space_extend_domain_with_range(isl_space_copy(domain), |
1610 | FN(PW,get_space)isl_pw_qpolynomial_get_space(pw)); |
1611 | return FN(PW,reset_space_and_domain)isl_pw_qpolynomial_reset_space_and_domain(pw, space, domain); |
1612 | } |
1613 | |
1614 | __isl_give PWisl_pw_qpolynomial *FN(PW,reset_space)isl_pw_qpolynomial_reset_space(__isl_take PWisl_pw_qpolynomial *pw, |
1615 | __isl_take isl_space *space) |
1616 | { |
1617 | isl_space *domain; |
1618 | |
1619 | domain = isl_space_domain(isl_space_copy(space)); |
1620 | return FN(PW,reset_space_and_domain)isl_pw_qpolynomial_reset_space_and_domain(pw, space, domain); |
1621 | } |
1622 | |
1623 | __isl_give PWisl_pw_qpolynomial *FN(PW,set_tuple_id)isl_pw_qpolynomial_set_tuple_id(__isl_take PWisl_pw_qpolynomial *pw, enum isl_dim_type type, |
1624 | __isl_take isl_id *id) |
1625 | { |
1626 | isl_space *space; |
1627 | |
1628 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1629 | if (!pw) |
1630 | goto error; |
1631 | |
1632 | space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1633 | space = isl_space_set_tuple_id(space, type, id); |
1634 | |
1635 | return FN(PW,reset_space)isl_pw_qpolynomial_reset_space(pw, space); |
1636 | error: |
1637 | isl_id_free(id); |
1638 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1639 | } |
1640 | |
1641 | /* Drop the id on the specified tuple. |
1642 | */ |
1643 | __isl_give PWisl_pw_qpolynomial *FN(PW,reset_tuple_id)isl_pw_qpolynomial_reset_tuple_id(__isl_take PWisl_pw_qpolynomial *pw, enum isl_dim_type type) |
1644 | { |
1645 | isl_space *space; |
1646 | |
1647 | if (!pw) |
1648 | return NULL((void*)0); |
1649 | if (!FN(PW,has_tuple_id)isl_pw_qpolynomial_has_tuple_id(pw, type)) |
1650 | return pw; |
1651 | |
1652 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1653 | if (!pw) |
1654 | return NULL((void*)0); |
1655 | |
1656 | space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1657 | space = isl_space_reset_tuple_id(space, type); |
1658 | |
1659 | return FN(PW,reset_space)isl_pw_qpolynomial_reset_space(pw, space); |
1660 | } |
1661 | |
1662 | __isl_give PWisl_pw_qpolynomial *FN(PW,set_dim_id)isl_pw_qpolynomial_set_dim_id(__isl_take PWisl_pw_qpolynomial *pw, |
1663 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
1664 | { |
1665 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1666 | if (!pw) |
1667 | goto error; |
1668 | pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id); |
1669 | return FN(PW,reset_space)isl_pw_qpolynomial_reset_space(pw, isl_space_copy(pw->dim)); |
1670 | error: |
1671 | isl_id_free(id); |
1672 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1673 | } |
1674 | |
1675 | /* Reset the user pointer on all identifiers of parameters and tuples |
1676 | * of the space of "pw". |
1677 | */ |
1678 | __isl_give PWisl_pw_qpolynomial *FN(PW,reset_user)isl_pw_qpolynomial_reset_user(__isl_take PWisl_pw_qpolynomial *pw) |
1679 | { |
1680 | isl_space *space; |
1681 | |
1682 | space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1683 | space = isl_space_reset_user(space); |
1684 | |
1685 | return FN(PW,reset_space)isl_pw_qpolynomial_reset_space(pw, space); |
1686 | } |
1687 | |
1688 | isl_size FN(PW,n_piece)isl_pw_qpolynomial_n_piece(__isl_keep PWisl_pw_qpolynomial *pw) |
1689 | { |
1690 | return pw ? pw->n : isl_size_error((int) -1); |
1691 | } |
1692 | |
1693 | isl_stat FN(PW,foreach_piece)isl_pw_qpolynomial_foreach_piece(__isl_keep PWisl_pw_qpolynomial *pw, |
1694 | isl_stat (*fn)(__isl_take isl_setisl_map *set, __isl_take ELisl_pw_qpolynomial *el, void *user), |
1695 | void *user) |
1696 | { |
1697 | int i; |
1698 | |
1699 | if (!pw) |
1700 | return isl_stat_error; |
1701 | |
1702 | for (i = 0; i < pw->n; ++i) |
1703 | if (fn(isl_set_copy(pw->p[i].set), |
1704 | FN(EL,copy)isl_pw_qpolynomial_copy(pw->p[i].FIELDqp), user) < 0) |
1705 | return isl_stat_error; |
1706 | |
1707 | return isl_stat_ok; |
1708 | } |
1709 | |
1710 | /* Does "test" succeed on every cell of "pw"? |
1711 | */ |
1712 | isl_bool FN(PW,every_piece)isl_pw_qpolynomial_every_piece(__isl_keep PWisl_pw_qpolynomial *pw, |
1713 | isl_bool (*test)(__isl_keep isl_setisl_map *set, |
1714 | __isl_keep ELisl_pw_qpolynomial *el, void *user), void *user) |
1715 | { |
1716 | int i; |
1717 | |
1718 | if (!pw) |
1719 | return isl_bool_error; |
1720 | |
1721 | for (i = 0; i < pw->n; ++i) { |
1722 | isl_bool r; |
1723 | |
1724 | r = test(pw->p[i].set, pw->p[i].FIELDqp, user); |
1725 | if (r < 0 || !r) |
1726 | return r; |
1727 | } |
1728 | |
1729 | return isl_bool_true; |
1730 | } |
1731 | |
1732 | /* Is "pw" defined over a single universe domain? |
1733 | * |
1734 | * If the default value of this piecewise type is zero, |
1735 | * then a "pw" with a zero number of cells is also accepted |
1736 | * as it represents the default zero value. |
1737 | */ |
1738 | isl_bool FN(FN(PW,isa),BASE)isl_pw_qpolynomial_isa_pw_qpolynomial(__isl_keep PWisl_pw_qpolynomial *pw) |
1739 | { |
1740 | isl_size n; |
1741 | |
1742 | n = FN(PW,n_piece)isl_pw_qpolynomial_n_piece(pw); |
1743 | if (n < 0) |
1744 | return isl_bool_error; |
1745 | if (DEFAULT_IS_ZERO1 && n == 0) |
1746 | return isl_bool_true; |
1747 | if (n != 1) |
1748 | return isl_bool_false; |
1749 | return isl_set_plain_is_universe(FN(PW,peek_domain_at)isl_pw_qpolynomial_peek_domain_at(pw, 0)); |
1750 | } |
1751 | |
1752 | /* Return a zero base expression in the same space (and of the same type) |
1753 | * as "pw". |
1754 | */ |
1755 | static __isl_give ELisl_pw_qpolynomial *FN(EL,zero_like_type)isl_pw_qpolynomial_zero_like_type(__isl_take PWisl_pw_qpolynomial *pw OPT_TYPE_PARAM) |
1756 | { |
1757 | isl_space *space; |
1758 | |
1759 | space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1760 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1761 | return FN(EL,zero_in_space)isl_pw_qpolynomial_zero_in_space(space OPT_TYPE_ARG(NO_LOC)); |
1762 | } |
1763 | |
1764 | #ifndef HAS_TYPE |
1765 | /* Return a zero base expression in the same space as "pw". |
1766 | */ |
1767 | static __isl_give ELisl_pw_qpolynomial *FN(EL,zero_like)isl_pw_qpolynomial_zero_like(__isl_take PWisl_pw_qpolynomial *pw) |
1768 | { |
1769 | return FN(EL,zero_like_type)isl_pw_qpolynomial_zero_like_type(pw); |
1770 | } |
1771 | #else |
1772 | /* Return a zero base expression in the same space and of the same type |
1773 | * as "pw". |
1774 | * |
1775 | * Pass along the type as an explicit argument for uniform handling |
1776 | * in isl_*_zero_like_type. |
1777 | */ |
1778 | static __isl_give ELisl_pw_qpolynomial *FN(EL,zero_like)isl_pw_qpolynomial_zero_like(__isl_take PWisl_pw_qpolynomial *pw) |
1779 | { |
1780 | enum isl_fold type; |
1781 | |
1782 | type = FN(PW,get_type)isl_pw_qpolynomial_get_type(pw); |
1783 | if (type < 0) |
1784 | goto error; |
1785 | return FN(EL,zero_like_type)isl_pw_qpolynomial_zero_like_type(pw, type); |
1786 | error: |
1787 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1788 | return NULL((void*)0); |
1789 | } |
1790 | #endif |
1791 | |
1792 | /* Given that "pw" is defined over a single universe domain, |
1793 | * return the base expression associated to this domain. |
1794 | * |
1795 | * If the number of cells is zero, then "pw" is of a piecewise type |
1796 | * with a default zero value and effectively represents zero. |
1797 | * In this case, create a zero base expression in the same space |
1798 | * (and with the same type). |
1799 | * Otherwise, simply extract the associated base expression. |
1800 | */ |
1801 | __isl_give ELisl_pw_qpolynomial *FN(FN(PW,as),BASE)isl_pw_qpolynomial_as_pw_qpolynomial(__isl_take PWisl_pw_qpolynomial *pw) |
1802 | { |
1803 | isl_bool is_total; |
1804 | isl_size n; |
1805 | ELisl_pw_qpolynomial *el; |
1806 | |
1807 | is_total = FN(FN(PW,isa),BASE)isl_pw_qpolynomial_isa_pw_qpolynomial(pw); |
1808 | if (is_total < 0) |
1809 | goto error; |
1810 | if (!is_total) |
1811 | isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "expecting single total function", "polly/lib/External/isl/isl_pw_templ.c" , 1812); goto error; } while (0) |
1812 | "expecting single total function", goto error)do { isl_handle_error(isl_pw_qpolynomial_get_ctx(pw), isl_error_invalid , "expecting single total function", "polly/lib/External/isl/isl_pw_templ.c" , 1812); goto error; } while (0); |
1813 | n = FN(PW,n_piece)isl_pw_qpolynomial_n_piece(pw); |
1814 | if (n < 0) |
1815 | goto error; |
1816 | if (n == 0) |
1817 | return FN(EL,zero_like)isl_pw_qpolynomial_zero_like(pw); |
1818 | el = FN(PW,take_base_at)isl_pw_qpolynomial_take_base_at(pw, 0); |
1819 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1820 | return el; |
1821 | error: |
1822 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1823 | return NULL((void*)0); |
1824 | } |
1825 | |
1826 | #ifdef HAS_TYPE |
1827 | /* Negate the type of "pw". |
1828 | */ |
1829 | static __isl_give PWisl_pw_qpolynomial *FN(PW,negate_type)isl_pw_qpolynomial_negate_type(__isl_take PWisl_pw_qpolynomial *pw) |
1830 | { |
1831 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1832 | if (!pw) |
1833 | return NULL((void*)0); |
1834 | pw->type = isl_fold_type_negate(pw->type); |
1835 | return pw; |
1836 | } |
1837 | #else |
1838 | /* Negate the type of "pw". |
1839 | * Since "pw" does not have a type, do nothing. |
1840 | */ |
1841 | static __isl_give PWisl_pw_qpolynomial *FN(PW,negate_type)isl_pw_qpolynomial_negate_type(__isl_take PWisl_pw_qpolynomial *pw) |
1842 | { |
1843 | return pw; |
1844 | } |
1845 | #endif |
1846 | |
1847 | __isl_give PWisl_pw_qpolynomial *FN(PW,mul_isl_int)isl_pw_qpolynomial_mul_isl_int(__isl_take PWisl_pw_qpolynomial *pw, isl_int v) |
1848 | { |
1849 | int i; |
1850 | |
1851 | if (isl_int_is_one(v)(isl_sioimath_cmp_si(*(v), 1) == 0)) |
1852 | return pw; |
1853 | if (pw && DEFAULT_IS_ZERO1 && isl_int_is_zero(v)(isl_sioimath_sgn(*(v)) == 0)) { |
1854 | PWisl_pw_qpolynomial *zero; |
1855 | isl_space *space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1856 | zero = FN(PW,ZERO)isl_pw_qpolynomial_zero(space OPT_TYPE_ARG(pw->)); |
1857 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1858 | return zero; |
1859 | } |
1860 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1861 | if (isl_int_is_neg(v)(isl_sioimath_sgn(*(v)) < 0)) |
1862 | pw = FN(PW,negate_type)isl_pw_qpolynomial_negate_type(pw); |
1863 | if (!pw) |
1864 | return NULL((void*)0); |
1865 | if (pw->n == 0) |
1866 | return pw; |
1867 | |
1868 | for (i = 0; i < pw->n; ++i) { |
1869 | pw->p[i].FIELDqp = FN(EL,scale)isl_pw_qpolynomial_scale(pw->p[i].FIELDqp, v); |
1870 | if (!pw->p[i].FIELDqp) |
1871 | goto error; |
1872 | } |
1873 | |
1874 | return pw; |
1875 | error: |
1876 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1877 | return NULL((void*)0); |
1878 | } |
1879 | |
1880 | /* Multiply the pieces of "pw" by "v" and return the result. |
1881 | */ |
1882 | __isl_give PWisl_pw_qpolynomial *FN(PW,scale_val)isl_pw_qpolynomial_scale_val(__isl_take PWisl_pw_qpolynomial *pw, __isl_take isl_val *v) |
1883 | { |
1884 | int i; |
1885 | |
1886 | if (!pw || !v) |
1887 | goto error; |
1888 | |
1889 | if (isl_val_is_one(v)) { |
1890 | isl_val_free(v); |
1891 | return pw; |
1892 | } |
1893 | if (pw && DEFAULT_IS_ZERO1 && isl_val_is_zero(v)) { |
1894 | PWisl_pw_qpolynomial *zero; |
1895 | isl_space *space = FN(PW,get_space)isl_pw_qpolynomial_get_space(pw); |
1896 | zero = FN(PW,ZERO)isl_pw_qpolynomial_zero(space OPT_TYPE_ARG(pw->)); |
1897 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1898 | isl_val_free(v); |
1899 | return zero; |
1900 | } |
1901 | if (pw->n == 0) { |
1902 | isl_val_free(v); |
1903 | return pw; |
1904 | } |
1905 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1906 | if (isl_val_is_neg(v)) |
1907 | pw = FN(PW,negate_type)isl_pw_qpolynomial_negate_type(pw); |
1908 | if (!pw) |
1909 | goto error; |
1910 | |
1911 | for (i = 0; i < pw->n; ++i) { |
1912 | pw->p[i].FIELDqp = FN(EL,scale_val)isl_pw_qpolynomial_scale_val(pw->p[i].FIELDqp, |
1913 | isl_val_copy(v)); |
1914 | if (!pw->p[i].FIELDqp) |
1915 | goto error; |
1916 | } |
1917 | |
1918 | isl_val_free(v); |
1919 | return pw; |
1920 | error: |
1921 | isl_val_free(v); |
1922 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1923 | return NULL((void*)0); |
1924 | } |
1925 | |
1926 | /* Divide the pieces of "pw" by "v" and return the result. |
1927 | */ |
1928 | __isl_give PWisl_pw_qpolynomial *FN(PW,scale_down_val)isl_pw_qpolynomial_scale_down_val(__isl_take PWisl_pw_qpolynomial *pw, __isl_take isl_val *v) |
1929 | { |
1930 | int i; |
1931 | |
1932 | if (!pw || !v) |
1933 | goto error; |
1934 | |
1935 | if (isl_val_is_one(v)) { |
1936 | isl_val_free(v); |
1937 | return pw; |
1938 | } |
1939 | |
1940 | if (!isl_val_is_rat(v)) |
1941 | isl_die(isl_val_get_ctx(v), isl_error_invalid,do { isl_handle_error(isl_val_get_ctx(v), isl_error_invalid, "expecting rational factor" , "polly/lib/External/isl/isl_pw_templ.c", 1942); goto error; } while (0) |
1942 | "expecting rational factor", goto error)do { isl_handle_error(isl_val_get_ctx(v), isl_error_invalid, "expecting rational factor" , "polly/lib/External/isl/isl_pw_templ.c", 1942); goto error; } while (0); |
1943 | if (isl_val_is_zero(v)) |
1944 | isl_die(isl_val_get_ctx(v), isl_error_invalid,do { isl_handle_error(isl_val_get_ctx(v), isl_error_invalid, "cannot scale down by zero" , "polly/lib/External/isl/isl_pw_templ.c", 1945); goto error; } while (0) |
1945 | "cannot scale down by zero", goto error)do { isl_handle_error(isl_val_get_ctx(v), isl_error_invalid, "cannot scale down by zero" , "polly/lib/External/isl/isl_pw_templ.c", 1945); goto error; } while (0); |
1946 | |
1947 | if (pw->n == 0) { |
1948 | isl_val_free(v); |
1949 | return pw; |
1950 | } |
1951 | pw = FN(PW,cow)isl_pw_qpolynomial_cow(pw); |
1952 | if (isl_val_is_neg(v)) |
1953 | pw = FN(PW,negate_type)isl_pw_qpolynomial_negate_type(pw); |
1954 | if (!pw) |
1955 | goto error; |
1956 | |
1957 | for (i = 0; i < pw->n; ++i) { |
1958 | pw->p[i].FIELDqp = FN(EL,scale_down_val)isl_pw_qpolynomial_scale_down_val(pw->p[i].FIELDqp, |
1959 | isl_val_copy(v)); |
1960 | if (!pw->p[i].FIELDqp) |
1961 | goto error; |
1962 | } |
1963 | |
1964 | isl_val_free(v); |
1965 | return pw; |
1966 | error: |
1967 | isl_val_free(v); |
1968 | FN(PW,free)isl_pw_qpolynomial_free(pw); |
1969 | return NULL((void*)0); |
1970 | } |
1971 | |
1972 | __isl_give PWisl_pw_qpolynomial *FN(PW,scale)isl_pw_qpolynomial_scale(__isl_take PWisl_pw_qpolynomial *pw, isl_int v) |
1973 | { |
1974 | return FN(PW,mul_isl_int)isl_pw_qpolynomial_mul_isl_int(pw, v); |
1975 | } |
1976 | |
1977 | /* Apply some normalization to "pw". |
1978 | * In particular, sort the pieces according to their function value |
1979 | * expressions, combining pairs of adjacent pieces with |
1980 | * the same such expression, and then normalize the domains of the pieces. |
1981 | * |
1982 | * We normalize in place, but if anything goes wrong we need |
1983 | * to return NULL, so we need to make sure we don't change the |
1984 | * meaning of any possible other copies of "pw". |
1985 | */ |
1986 | __isl_give PWisl_pw_qpolynomial *FN(PW,normalize)isl_pw_qpolynomial_normalize(__isl_take PWisl_pw_qpolynomial *pw) |
1987 | { |
1988 | int i; |
1989 | isl_setisl_map *set; |
1990 | |
1991 | pw = FN(PW,sort)isl_pw_qpolynomial_sort(pw); |
1992 | if (!pw) |
1993 | return NULL((void*)0); |
1994 | for (i = 0; i < pw->n; ++i) { |
1995 | set = isl_set_normalize(isl_set_copy(pw->p[i].set)); |
1996 | if (!set) |
1997 | return FN(PW,free)isl_pw_qpolynomial_free(pw); |
1998 | isl_set_free(pw->p[i].set); |
1999 | pw->p[i].set = set; |
2000 | } |
2001 | |
2002 | return pw; |
2003 | } |
2004 | |
2005 | /* Is pw1 obviously equal to pw2? |
2006 | * That is, do they have obviously identical cells and obviously identical |
2007 | * elements on each cell? |
2008 | * |
2009 | * If "pw1" or "pw2" contain any NaNs, then they are considered |
2010 | * not to be the same. A NaN is not equal to anything, not even |
2011 | * to another NaN. |
2012 | */ |
2013 | isl_bool FN(PW,plain_is_equal)isl_pw_qpolynomial_plain_is_equal(__isl_keep PWisl_pw_qpolynomial *pw1, __isl_keep PWisl_pw_qpolynomial *pw2) |
2014 | { |
2015 | int i; |
2016 | isl_bool equal, has_nan; |
2017 | |
2018 | if (!pw1 || !pw2) |
2019 | return isl_bool_error; |
2020 | |
2021 | has_nan = FN(PW,involves_nan)isl_pw_qpolynomial_involves_nan(pw1); |
2022 | if (has_nan >= 0 && !has_nan) |
2023 | has_nan = FN(PW,involves_nan)isl_pw_qpolynomial_involves_nan(pw2); |
2024 | if (has_nan < 0 || has_nan) |
2025 | return isl_bool_not(has_nan); |
2026 | |
2027 | if (pw1 == pw2) |
2028 | return isl_bool_true; |
2029 | equal = FN(PW,has_equal_space)isl_pw_qpolynomial_has_equal_space(pw1, pw2); |
2030 | if (equal < 0 || !equal) |
2031 | return equal; |
2032 | |
2033 | pw1 = FN(PW,copy)isl_pw_qpolynomial_copy(pw1); |
2034 | pw2 = FN(PW,copy)isl_pw_qpolynomial_copy(pw2); |
2035 | pw1 = FN(PW,normalize)isl_pw_qpolynomial_normalize(pw1); |
2036 | pw2 = FN(PW,normalize)isl_pw_qpolynomial_normalize(pw2); |
2037 | if (!pw1 || !pw2) |
2038 | goto error; |
2039 | |
2040 | equal = isl_bool_ok(pw1->n == pw2->n); |
2041 | for (i = 0; equal && i < pw1->n; ++i) { |
2042 | equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set); |
2043 | if (equal < 0) |
2044 | goto error; |
2045 | if (!equal) |
2046 | break; |
2047 | equal = FN(EL,plain_is_equal)isl_pw_qpolynomial_plain_is_equal(pw1->p[i].FIELDqp, pw2->p[i].FIELDqp); |
2048 | if (equal < 0) |
2049 | goto error; |
2050 | } |
2051 | |
2052 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
2053 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
2054 | return equal; |
2055 | error: |
2056 | FN(PW,free)isl_pw_qpolynomial_free(pw1); |
2057 | FN(PW,free)isl_pw_qpolynomial_free(pw2); |
2058 | return isl_bool_error; |
2059 | } |
2060 | |
2061 | /* Does "pw" involve any NaNs? |
2062 | */ |
2063 | isl_bool FN(PW,involves_nan)isl_pw_qpolynomial_involves_nan(__isl_keep PWisl_pw_qpolynomial *pw) |
2064 | { |
2065 | int i; |
2066 | |
2067 | if (!pw) |
2068 | return isl_bool_error; |
2069 | if (pw->n == 0) |
2070 | return isl_bool_false; |
2071 | |
2072 | for (i = 0; i < pw->n; ++i) { |
2073 | isl_bool has_nan = FN(EL,involves_nan)isl_pw_qpolynomial_involves_nan(pw->p[i].FIELDqp); |
2074 | if (has_nan < 0 || has_nan) |
2075 | return has_nan; |
2076 | } |
2077 | |
2078 | return isl_bool_false; |
2079 | } |