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