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