2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 #include <isl_map_private.h>
12 #include <isl_union_map_private.h>
13 #include <isl_polynomial_private.h>
14 #include <isl_point_private.h>
15 #include <isl_space_private.h>
16 #include <isl_lp_private.h>
18 #include <isl_mat_private.h>
19 #include <isl_val_private.h>
20 #include <isl_vec_private.h>
21 #include <isl_config.h>
24 #define EL_BASE pw_qpolynomial_fold
26 #include <isl_list_templ.c>
28 enum isl_fold
isl_fold_type_negate(enum isl_fold type
)
32 return isl_fold_error
;
41 isl_die(NULL
, isl_error_internal
, "unhandled isl_fold type", abort());
44 /* Construct a new reduction with the given type, domain space and
45 * list of polynomials.
47 static __isl_give isl_qpolynomial_fold
*qpolynomial_fold_alloc(
48 enum isl_fold type
, __isl_take isl_space
*space
,
49 __isl_take isl_qpolynomial_list
*list
)
52 isl_qpolynomial_fold
*fold
;
54 if (type
< 0 || !space
|| !list
)
57 ctx
= isl_space_get_ctx(space
);
58 fold
= isl_calloc_type(ctx
, struct isl_qpolynomial_fold
);
69 isl_space_free(space
);
70 isl_qpolynomial_list_free(list
);
74 isl_ctx
*isl_qpolynomial_fold_get_ctx(__isl_keep isl_qpolynomial_fold
*fold
)
76 return fold
? fold
->dim
->ctx
: NULL
;
79 /* Return the domain space of "fold".
81 static __isl_keep isl_space
*isl_qpolynomial_fold_peek_domain_space(
82 __isl_keep isl_qpolynomial_fold
*fold
)
84 return fold
? fold
->dim
: NULL
;
87 __isl_give isl_space
*isl_qpolynomial_fold_get_domain_space(
88 __isl_keep isl_qpolynomial_fold
*fold
)
90 return isl_space_copy(isl_qpolynomial_fold_peek_domain_space(fold
));
93 /* Return the space of the domain of "fold".
94 * This may be either a copy or the space itself
95 * if there is only one reference to "fold".
96 * This allows the space to be modified inplace
97 * if both the expression and its space have only a single reference.
98 * The caller is not allowed to modify "fold" between this call and
99 * a subsequent call to isl_qpolynomial_fold_restore_domain_space.
100 * The only exception is that isl_qpolynomial_fold_free can be called instead.
102 static __isl_give isl_space
*isl_qpolynomial_fold_take_domain_space(
103 __isl_keep isl_qpolynomial_fold
*fold
)
110 return isl_qpolynomial_fold_get_domain_space(fold
);
116 /* Set the space of the domain of "fold" to "space",
117 * where the space of "fold" may be missing
118 * due to a preceding call to isl_qpolynomial_fold_take_domain_space.
119 * However, in this case, "fold" only has a single reference and
120 * then the call to isl_qpolynomial_fold_cow has no effect.
123 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_restore_domain_space(
124 __isl_keep isl_qpolynomial_fold
*fold
, __isl_take isl_space
*space
)
129 if (fold
->dim
== space
) {
130 isl_space_free(space
);
134 fold
= isl_qpolynomial_fold_cow(fold
);
137 isl_space_free(fold
->dim
);
142 isl_qpolynomial_fold_free(fold
);
143 isl_space_free(space
);
147 __isl_give isl_space
*isl_qpolynomial_fold_get_space(
148 __isl_keep isl_qpolynomial_fold
*fold
)
153 space
= isl_space_copy(fold
->dim
);
154 space
= isl_space_from_domain(space
);
155 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
159 /* Return the list of polynomials in the reduction "fold".
161 __isl_keep isl_qpolynomial_list
*isl_qpolynomial_fold_peek_list(
162 __isl_keep isl_qpolynomial_fold
*fold
)
164 return fold
? fold
->list
: NULL
;
167 /* Return a copy of the list of polynomials in the reduction "fold".
169 static __isl_give isl_qpolynomial_list
*isl_qpolynomial_fold_get_list(
170 __isl_keep isl_qpolynomial_fold
*fold
)
172 return isl_qpolynomial_list_copy(isl_qpolynomial_fold_peek_list(fold
));
175 /* Return the list of polynomials of "fold".
176 * This may be either a copy or the list itself
177 * if there is only one reference to "fold".
178 * This allows the list to be modified inplace
179 * if both the expression and its list have only a single reference.
180 * The caller is not allowed to modify "fold" between this call and
181 * a subsequent call to isl_qpolynomial_fold_restore_list.
182 * The only exception is that isl_qpolynomial_fold_free can be called instead.
184 static __isl_give isl_qpolynomial_list
*isl_qpolynomial_fold_take_list(
185 __isl_keep isl_qpolynomial_fold
*fold
)
187 isl_qpolynomial_list
*list
;
192 return isl_qpolynomial_fold_get_list(fold
);
198 /* Set the space of the list of polynomials of "fold" to "space",
199 * where the list of polynomials of "fold" may be missing
200 * due to a preceding call to isl_qpolynomial_fold_take_list.
201 * However, in this case, "fold" only has a single reference and
202 * then the call to isl_qpolynomial_fold_cow has no effect.
204 static __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_restore_list(
205 __isl_keep isl_qpolynomial_fold
*fold
,
206 __isl_take isl_qpolynomial_list
*list
)
211 if (fold
->list
== list
) {
212 isl_qpolynomial_list_free(list
);
216 fold
= isl_qpolynomial_fold_cow(fold
);
219 isl_qpolynomial_list_free(fold
->list
);
224 isl_qpolynomial_fold_free(fold
);
225 isl_qpolynomial_list_free(list
);
229 /* isl_qpolynomial_list_map callback that calls
230 * isl_qpolynomial_reset_domain_space on "qp".
232 static __isl_give isl_qpolynomial
*reset_domain_space(
233 __isl_take isl_qpolynomial
*qp
, void *user
)
235 isl_space
*space
= user
;
237 return isl_qpolynomial_reset_domain_space(qp
, isl_space_copy(space
));
240 /* Replace the domain space of "fold" by "space".
242 * Replace the domain space itself and that of all polynomials
245 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_reset_domain_space(
246 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_space
*space
)
248 isl_qpolynomial_list
*list
;
250 list
= isl_qpolynomial_fold_take_list(fold
);
251 list
= isl_qpolynomial_list_map(list
, &reset_domain_space
, space
);
252 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
254 isl_space_free(isl_qpolynomial_fold_take_domain_space(fold
));
255 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
260 /* Reset the space of "fold". This function is called from isl_pw_templ.c
261 * and doesn't know if the space of an element object is represented
262 * directly or through its domain. It therefore passes along both.
264 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_reset_space_and_domain(
265 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_space
*space
,
266 __isl_take isl_space
*domain
)
268 isl_space_free(space
);
269 return isl_qpolynomial_fold_reset_domain_space(fold
, domain
);
272 /* Internal data structure for isl_qpolynomial_fold_*_dims
273 * representing their arguments.
275 struct isl_fold_dims_data
{
276 enum isl_dim_type type
;
281 /* isl_qpolynomial_list_every callback that checks whether "qp"
282 * does not involve any dimensions in the given range.
284 static isl_bool
not_involved(__isl_keep isl_qpolynomial
*qp
, void *user
)
286 struct isl_fold_dims_data
*data
= user
;
289 involves
= isl_qpolynomial_involves_dims(qp
, data
->type
,
290 data
->first
, data
->n
);
291 return isl_bool_not(involves
);
294 /* Does "fold" involve any dimensions in the given range.
296 * It involves any of those dimensions if it is not the case
297 * that every polynomial in the reduction does not involve
298 * any of the dimensions.
300 static isl_bool
isl_qpolynomial_fold_involves_dims(
301 __isl_keep isl_qpolynomial_fold
*fold
,
302 enum isl_dim_type type
, unsigned first
, unsigned n
)
304 struct isl_fold_dims_data data
= { type
, first
, n
};
305 isl_qpolynomial_list
*list
;
309 return isl_bool_error
;
311 return isl_bool_false
;
313 list
= isl_qpolynomial_fold_peek_list(fold
);
314 not = isl_qpolynomial_list_every(list
, ¬_involved
, &data
);
315 return isl_bool_not(not);
318 /* Internal data structure for isl_qpolynomial_fold_set_dim_name
319 * representing its arguments.
321 struct isl_fold_set_dim_name_data
{
322 enum isl_dim_type type
;
327 /* isl_qpolynomial_list_map callback for calling
328 * isl_qpolynomial_set_dim_name on "qp".
330 static __isl_give isl_qpolynomial
*set_dim_name(__isl_take isl_qpolynomial
*qp
,
333 struct isl_fold_set_dim_name_data
*data
= user
;
335 qp
= isl_qpolynomial_set_dim_name(qp
, data
->type
, data
->pos
, data
->s
);
339 /* Given a dimension type for an isl_qpolynomial_fold,
340 * return the corresponding type for the domain.
342 static enum isl_dim_type
domain_type(enum isl_dim_type type
)
344 if (type
== isl_dim_in
)
349 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_set_dim_name(
350 __isl_take isl_qpolynomial_fold
*fold
,
351 enum isl_dim_type type
, unsigned pos
, const char *s
)
353 struct isl_fold_set_dim_name_data data
= { type
, pos
, s
};
354 enum isl_dim_type set_type
;
356 isl_qpolynomial_list
*list
;
358 list
= isl_qpolynomial_fold_take_list(fold
);
359 list
= isl_qpolynomial_list_map(list
, &set_dim_name
, &data
);
360 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
362 set_type
= domain_type(type
);
363 space
= isl_qpolynomial_fold_take_domain_space(fold
);
364 space
= isl_space_set_dim_name(space
, set_type
, pos
, s
);
365 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
370 /* isl_qpolynomial_list_map callback for calling
371 * isl_qpolynomial_drop_dims on "qp".
373 static __isl_give isl_qpolynomial
*drop_dims(__isl_take isl_qpolynomial
*qp
,
376 struct isl_fold_dims_data
*data
= user
;
378 qp
= isl_qpolynomial_drop_dims(qp
, data
->type
, data
->first
, data
->n
);
382 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_drop_dims(
383 __isl_take isl_qpolynomial_fold
*fold
,
384 enum isl_dim_type type
, unsigned first
, unsigned n
)
386 struct isl_fold_dims_data data
= { type
, first
, n
};
387 enum isl_dim_type set_type
;
389 isl_qpolynomial_list
*list
;
396 set_type
= domain_type(type
);
398 list
= isl_qpolynomial_fold_take_list(fold
);
399 list
= isl_qpolynomial_list_map(list
, &drop_dims
, &data
);
400 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
402 space
= isl_qpolynomial_fold_take_domain_space(fold
);
403 space
= isl_space_drop_dims(space
, set_type
, first
, n
);
404 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
409 /* isl_qpolynomial_list_map callback for calling
410 * isl_qpolynomial_insert_dims on "qp".
412 static __isl_give isl_qpolynomial
*insert_dims(__isl_take isl_qpolynomial
*qp
,
415 struct isl_fold_dims_data
*data
= user
;
417 qp
= isl_qpolynomial_insert_dims(qp
, data
->type
, data
->first
, data
->n
);
421 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_insert_dims(
422 __isl_take isl_qpolynomial_fold
*fold
,
423 enum isl_dim_type type
, unsigned first
, unsigned n
)
425 struct isl_fold_dims_data data
= { type
, first
, n
};
426 enum isl_dim_type set_type
;
428 isl_qpolynomial_list
*list
;
432 if (n
== 0 && !isl_space_is_named_or_nested(fold
->dim
, type
))
435 list
= isl_qpolynomial_fold_take_list(fold
);
436 list
= isl_qpolynomial_list_map(list
, &insert_dims
, &data
);
437 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
439 set_type
= domain_type(type
);
440 space
= isl_qpolynomial_fold_take_domain_space(fold
);
441 space
= isl_space_insert_dims(space
, set_type
, first
, n
);
442 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
447 /* Determine the sign of the constant quasipolynomial "qp".
454 * For qp == 0, we can return either -1 or 1. In practice, we return 1.
455 * For qp == NaN, the sign is undefined, so we return 0.
457 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial
*qp
)
461 if (isl_qpolynomial_is_nan(qp
))
464 cst
= isl_poly_as_cst(qp
->poly
);
468 return isl_int_sgn(cst
->n
) < 0 ? -1 : 1;
471 static int isl_qpolynomial_aff_sign(__isl_keep isl_set
*set
,
472 __isl_keep isl_qpolynomial
*qp
)
474 enum isl_lp_result res
;
479 aff
= isl_qpolynomial_extract_affine(qp
);
485 res
= isl_set_solve_lp(set
, 0, aff
->el
+ 1, aff
->el
[0],
487 if (res
== isl_lp_error
)
489 if (res
== isl_lp_empty
||
490 (res
== isl_lp_ok
&& !isl_int_is_neg(opt
))) {
495 res
= isl_set_solve_lp(set
, 1, aff
->el
+ 1, aff
->el
[0],
497 if (res
== isl_lp_ok
&& !isl_int_is_pos(opt
))
506 /* Determine, if possible, the sign of the quasipolynomial "qp" on
509 * If qp is a constant, then the problem is trivial.
510 * If qp is linear, then we check if the minimum of the corresponding
511 * affine constraint is non-negative or if the maximum is non-positive.
513 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
514 * in "set". If so, we write qp(v,v') as
516 * q(v,v') * (v - l) + r(v')
518 * if q(v,v') and r(v') have the same known sign, then the original
519 * quasipolynomial has the same sign as well.
526 static int isl_qpolynomial_sign(__isl_keep isl_set
*set
,
527 __isl_keep isl_qpolynomial
*qp
)
535 enum isl_lp_result res
;
538 is
= isl_qpolynomial_is_cst(qp
, NULL
, NULL
);
542 return isl_qpolynomial_cst_sign(qp
);
544 is
= isl_qpolynomial_is_affine(qp
);
548 return isl_qpolynomial_aff_sign(set
, qp
);
550 if (qp
->div
->n_row
> 0)
553 rec
= isl_poly_as_rec(qp
->poly
);
557 d
= isl_space_dim(qp
->dim
, isl_dim_all
);
560 v
= isl_vec_alloc(set
->ctx
, 2 + d
);
564 isl_seq_clr(v
->el
+ 1, 1 + d
);
565 isl_int_set_si(v
->el
[0], 1);
566 isl_int_set_si(v
->el
[2 + qp
->poly
->var
], 1);
570 res
= isl_set_solve_lp(set
, 0, v
->el
+ 1, v
->el
[0], &l
, NULL
, NULL
);
571 if (res
== isl_lp_ok
) {
572 isl_qpolynomial
*min
;
573 isl_qpolynomial
*base
;
574 isl_qpolynomial
*r
, *q
;
577 min
= isl_qpolynomial_cst_on_domain(isl_space_copy(qp
->dim
), l
);
578 base
= isl_qpolynomial_var_pow_on_domain(isl_space_copy(qp
->dim
),
581 r
= isl_qpolynomial_alloc(isl_space_copy(qp
->dim
), 0,
582 isl_poly_copy(rec
->p
[rec
->n
- 1]));
583 q
= isl_qpolynomial_copy(r
);
585 for (i
= rec
->n
- 2; i
>= 0; --i
) {
586 r
= isl_qpolynomial_mul(r
, isl_qpolynomial_copy(min
));
587 t
= isl_qpolynomial_alloc(isl_space_copy(qp
->dim
), 0,
588 isl_poly_copy(rec
->p
[i
]));
589 r
= isl_qpolynomial_add(r
, t
);
592 q
= isl_qpolynomial_mul(q
, isl_qpolynomial_copy(base
));
593 q
= isl_qpolynomial_add(q
, isl_qpolynomial_copy(r
));
596 if (isl_qpolynomial_is_zero(q
))
597 sgn
= isl_qpolynomial_sign(set
, r
);
598 else if (isl_qpolynomial_is_zero(r
))
599 sgn
= isl_qpolynomial_sign(set
, q
);
602 sgn_r
= isl_qpolynomial_sign(set
, r
);
603 sgn_q
= isl_qpolynomial_sign(set
, q
);
608 isl_qpolynomial_free(min
);
609 isl_qpolynomial_free(base
);
610 isl_qpolynomial_free(q
);
611 isl_qpolynomial_free(r
);
621 /* Check that "fold1" and "fold2" have the same type.
623 static isl_stat
isl_qpolynomial_fold_check_equal_type(
624 __isl_keep isl_qpolynomial_fold
*fold1
,
625 __isl_keep isl_qpolynomial_fold
*fold2
)
627 enum isl_fold type1
, type2
;
629 type1
= isl_qpolynomial_fold_get_type(fold1
);
630 type2
= isl_qpolynomial_fold_get_type(fold2
);
631 if (type1
< 0 || type2
< 0)
632 return isl_stat_error
;
634 isl_die(isl_qpolynomial_fold_get_ctx(fold1
), isl_error_invalid
,
635 "fold types don't match", return isl_stat_error
);
639 /* Check that "fold1" and "fold2" have the same (domain) space.
641 static isl_stat
isl_qpolynomial_fold_check_equal_space(
642 __isl_keep isl_qpolynomial_fold
*fold1
,
643 __isl_keep isl_qpolynomial_fold
*fold2
)
646 isl_space
*space1
, *space2
;
648 space1
= isl_qpolynomial_fold_peek_domain_space(fold1
);
649 space2
= isl_qpolynomial_fold_peek_domain_space(fold2
);
650 equal
= isl_space_is_equal(space1
, space2
);
652 return isl_stat_error
;
654 isl_die(isl_qpolynomial_fold_get_ctx(fold1
), isl_error_invalid
,
655 "spaces don't match", return isl_stat_error
);
659 /* Combine "list1" and "list2" into a single list, eliminating
660 * those elements of one list that are already covered by the other
663 * "better" is the sign that the difference qp1 - qp2 needs to have for qp1
664 * to be covered by qp2.
666 static __isl_give isl_qpolynomial_list
*merge_lists(__isl_keep isl_set
*set
,
667 __isl_take isl_qpolynomial_list
*list1
,
668 __isl_take isl_qpolynomial_list
*list2
, int better
)
673 n1
= isl_qpolynomial_list_size(list1
);
674 n2
= isl_qpolynomial_list_size(list2
);
675 if (n1
< 0 || n2
< 0)
678 for (i
= n2
- 1; i
>= 0; --i
) {
679 for (j
= n1
- 1; j
>= 0; --j
) {
680 isl_qpolynomial
*qp1
, *qp2
, *d
;
684 qp1
= isl_qpolynomial_list_peek(list1
, j
);
685 qp2
= isl_qpolynomial_list_peek(list2
, i
);
686 equal
= isl_qpolynomial_plain_is_equal(qp1
, qp2
);
691 d
= isl_qpolynomial_sub(
692 isl_qpolynomial_copy(qp1
),
693 isl_qpolynomial_copy(qp2
));
694 sgn
= isl_qpolynomial_sign(set
, d
);
695 isl_qpolynomial_free(d
);
700 list1
= isl_qpolynomial_list_drop(list1
, j
, 1);
705 list2
= isl_qpolynomial_list_drop(list2
, i
, 1);
709 return isl_qpolynomial_list_concat(list1
, list2
);
711 isl_qpolynomial_list_free(list1
);
712 isl_qpolynomial_list_free(list2
);
716 /* Combine "fold1" and "fold2" into a single reduction, eliminating
717 * those elements of one reduction that are already covered by the other
718 * reduction on "set".
720 * If "fold1" or "fold2" is an empty reduction, then return
721 * the other reduction.
722 * If "fold1" or "fold2" is a NaN, then return this NaN.
724 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_fold_on_domain(
725 __isl_keep isl_set
*set
,
726 __isl_take isl_qpolynomial_fold
*fold1
,
727 __isl_take isl_qpolynomial_fold
*fold2
)
729 isl_qpolynomial_list
*list1
;
730 isl_qpolynomial_list
*list2
;
733 if (isl_qpolynomial_fold_check_equal_type(fold1
, fold2
) < 0)
735 if (isl_qpolynomial_fold_check_equal_space(fold1
, fold2
) < 0)
738 better
= fold1
->type
== isl_fold_max
? -1 : 1;
740 if (isl_qpolynomial_fold_is_empty(fold1
) ||
741 isl_qpolynomial_fold_is_nan(fold2
)) {
742 isl_qpolynomial_fold_free(fold1
);
746 if (isl_qpolynomial_fold_is_empty(fold2
) ||
747 isl_qpolynomial_fold_is_nan(fold1
)) {
748 isl_qpolynomial_fold_free(fold2
);
752 list1
= isl_qpolynomial_fold_take_list(fold1
);
753 list2
= isl_qpolynomial_fold_take_list(fold2
);
755 list1
= merge_lists(set
, list1
, list2
, better
);
757 fold1
= isl_qpolynomial_fold_restore_list(fold1
, list1
);
758 isl_qpolynomial_fold_free(fold2
);
762 isl_qpolynomial_fold_free(fold1
);
763 isl_qpolynomial_fold_free(fold2
);
767 /* isl_qpolynomial_list_map callback for adding "qp2" to "qp".
769 static __isl_give isl_qpolynomial
*add_qpolynomial(
770 __isl_take isl_qpolynomial
*qp
, void *user
)
772 isl_qpolynomial
*qp2
= user
;
774 return isl_qpolynomial_add(qp
, isl_qpolynomial_copy(qp2
));
777 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_add_qpolynomial(
778 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_qpolynomial
*qp
)
780 isl_qpolynomial_list
*list
;
785 if (isl_qpolynomial_is_zero(qp
)) {
786 isl_qpolynomial_free(qp
);
790 list
= isl_qpolynomial_fold_take_list(fold
);
791 list
= isl_qpolynomial_list_map(list
, &add_qpolynomial
, qp
);
792 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
794 isl_qpolynomial_free(qp
);
797 isl_qpolynomial_fold_free(fold
);
798 isl_qpolynomial_free(qp
);
802 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_add_on_domain(
803 __isl_keep isl_set
*dom
,
804 __isl_take isl_qpolynomial_fold
*fold1
,
805 __isl_take isl_qpolynomial_fold
*fold2
)
809 isl_qpolynomial_fold
*res
= NULL
;
811 isl_qpolynomial_list
*list1
, *list2
;
813 if (!fold1
|| !fold2
)
816 if (isl_qpolynomial_fold_is_empty(fold1
)) {
817 isl_qpolynomial_fold_free(fold1
);
821 if (isl_qpolynomial_fold_is_empty(fold2
)) {
822 isl_qpolynomial_fold_free(fold2
);
826 list1
= isl_qpolynomial_fold_peek_list(fold1
);
827 list2
= isl_qpolynomial_fold_peek_list(fold2
);
828 n1
= isl_qpolynomial_list_size(list1
);
829 n2
= isl_qpolynomial_list_size(list2
);
830 if (n1
< 0 || n2
< 0)
833 if (n1
== 1 && n2
!= 1)
834 return isl_qpolynomial_fold_add_on_domain(dom
, fold2
, fold1
);
836 qp
= isl_qpolynomial_list_get_at(list2
, 0);
838 res
= isl_qpolynomial_fold_add_qpolynomial(fold1
, qp
);
839 isl_qpolynomial_fold_free(fold2
);
843 res
= isl_qpolynomial_fold_add_qpolynomial(
844 isl_qpolynomial_fold_copy(fold1
), qp
);
846 for (i
= 1; i
< n2
; ++i
) {
847 isl_qpolynomial_fold
*res_i
;
849 qp
= isl_qpolynomial_list_get_at(list2
, i
);
850 res_i
= isl_qpolynomial_fold_add_qpolynomial(
851 isl_qpolynomial_fold_copy(fold1
), qp
);
852 res
= isl_qpolynomial_fold_fold_on_domain(dom
, res
, res_i
);
855 isl_qpolynomial_fold_free(fold1
);
856 isl_qpolynomial_fold_free(fold2
);
859 isl_qpolynomial_fold_free(res
);
860 isl_qpolynomial_fold_free(fold1
);
861 isl_qpolynomial_fold_free(fold2
);
865 /* isl_qpolynomial_list_map callback for calling
866 * isl_qpolynomial_substitute_equalities on "qp" and "eq".
868 static __isl_give isl_qpolynomial
*substitute_equalities(
869 __isl_take isl_qpolynomial
*qp
, void *user
)
871 isl_basic_set
*eq
= user
;
873 eq
= isl_basic_set_copy(eq
);
874 return isl_qpolynomial_substitute_equalities(qp
, eq
);
877 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_substitute_equalities(
878 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_basic_set
*eq
)
880 isl_qpolynomial_list
*list
;
882 list
= isl_qpolynomial_fold_take_list(fold
);
883 list
= isl_qpolynomial_list_map(list
, &substitute_equalities
, eq
);
884 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
886 isl_basic_set_free(eq
);
890 /* isl_qpolynomial_list_map callback for calling
891 * isl_qpolynomial_substitute_equalities on "qp" and "context".
893 static __isl_give isl_qpolynomial
*gist(__isl_take isl_qpolynomial
*qp
,
896 isl_set
*context
= user
;
898 return isl_qpolynomial_gist(qp
, isl_set_copy(context
));
901 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_gist(
902 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_set
*context
)
904 isl_qpolynomial_list
*list
;
906 list
= isl_qpolynomial_fold_take_list(fold
);
907 list
= isl_qpolynomial_list_map(list
, &gist
, context
);
908 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
910 isl_set_free(context
);
914 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_gist_params(
915 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_set
*context
)
917 isl_space
*space
= isl_qpolynomial_fold_get_domain_space(fold
);
918 isl_set
*dom_context
= isl_set_universe(space
);
919 dom_context
= isl_set_intersect_params(dom_context
, context
);
920 return isl_qpolynomial_fold_gist(fold
, dom_context
);
923 /* Return a zero (i.e., empty) isl_qpolynomial_fold in the given space.
925 * This is a helper function for isl_pw_*_as_* that ensures a uniform
926 * interface over all piecewise types.
928 static __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_zero_in_space(
929 __isl_take isl_space
*space
, enum isl_fold type
)
931 return isl_qpolynomial_fold_empty(type
, isl_space_domain(space
));
934 #define isl_qpolynomial_fold_involves_nan isl_qpolynomial_fold_is_nan
939 #define PW isl_pw_qpolynomial_fold
941 #define BASE qpolynomial_fold
943 #define EL_IS_ZERO is_empty
947 #define IS_ZERO is_zero
950 #undef DEFAULT_IS_ZERO
951 #define DEFAULT_IS_ZERO 1
953 #include <isl_pw_templ.c>
954 #include <isl_pw_add_disjoint_templ.c>
955 #include <isl_pw_eval.c>
956 #include <isl_pw_fix_templ.c>
957 #include <isl_pw_from_range_templ.c>
958 #include <isl_pw_insert_dims_templ.c>
959 #include <isl_pw_lift_templ.c>
960 #include <isl_pw_morph_templ.c>
961 #include <isl_pw_move_dims_templ.c>
962 #include <isl_pw_opt_templ.c>
965 #define BASE pw_qpolynomial_fold
967 #include <isl_union_single.c>
968 #include <isl_union_eval.c>
970 /* Construct a new reduction of the given type and space
971 * with an empty list of polynomials.
973 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_empty(enum isl_fold type
,
974 __isl_take isl_space
*space
)
977 isl_qpolynomial_list
*list
;
981 ctx
= isl_space_get_ctx(space
);
982 list
= isl_qpolynomial_list_alloc(ctx
, 0);
983 return qpolynomial_fold_alloc(type
, space
, list
);
986 /* Construct a new reduction of the given type and
987 * a single given polynomial.
989 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_alloc(
990 enum isl_fold type
, __isl_take isl_qpolynomial
*qp
)
993 isl_qpolynomial_list
*list
;
995 space
= isl_qpolynomial_get_domain_space(qp
);
996 list
= isl_qpolynomial_list_from_qpolynomial(qp
);
997 return qpolynomial_fold_alloc(type
, space
, list
);
1000 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_copy(
1001 __isl_keep isl_qpolynomial_fold
*fold
)
1010 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_dup(
1011 __isl_keep isl_qpolynomial_fold
*fold
)
1015 isl_qpolynomial_list
*list
;
1017 type
= isl_qpolynomial_fold_get_type(fold
);
1018 space
= isl_qpolynomial_fold_get_domain_space(fold
);
1019 list
= isl_qpolynomial_fold_get_list(fold
);
1020 return qpolynomial_fold_alloc(type
, space
, list
);
1023 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_cow(
1024 __isl_take isl_qpolynomial_fold
*fold
)
1032 return isl_qpolynomial_fold_dup(fold
);
1035 __isl_null isl_qpolynomial_fold
*isl_qpolynomial_fold_free(
1036 __isl_take isl_qpolynomial_fold
*fold
)
1040 if (--fold
->ref
> 0)
1043 isl_qpolynomial_list_free(fold
->list
);
1044 isl_space_free(fold
->dim
);
1050 isl_bool
isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold
*fold
)
1053 isl_qpolynomial_list
*list
;
1055 list
= isl_qpolynomial_fold_peek_list(fold
);
1056 n
= isl_qpolynomial_list_size(list
);
1058 return isl_bool_error
;
1060 return isl_bool_ok(n
== 0);
1063 /* Does "fold" represent max(NaN) or min(NaN)?
1065 isl_bool
isl_qpolynomial_fold_is_nan(__isl_keep isl_qpolynomial_fold
*fold
)
1068 isl_qpolynomial
*qp
;
1069 isl_qpolynomial_list
*list
;
1071 list
= isl_qpolynomial_fold_peek_list(fold
);
1072 n
= isl_qpolynomial_list_size(list
);
1074 return isl_bool_error
;
1076 return isl_bool_false
;
1077 qp
= isl_qpolynomial_list_peek(list
, 0);
1078 return isl_qpolynomial_is_nan(qp
);
1081 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_fold(
1082 __isl_take isl_qpolynomial_fold
*fold1
,
1083 __isl_take isl_qpolynomial_fold
*fold2
)
1085 isl_qpolynomial_list
*list1
, *list2
;
1087 if (isl_qpolynomial_fold_check_equal_type(fold1
, fold2
) < 0)
1089 if (isl_qpolynomial_fold_check_equal_space(fold1
, fold2
) < 0)
1092 if (isl_qpolynomial_fold_is_empty(fold1
)) {
1093 isl_qpolynomial_fold_free(fold1
);
1097 if (isl_qpolynomial_fold_is_empty(fold2
)) {
1098 isl_qpolynomial_fold_free(fold2
);
1102 list1
= isl_qpolynomial_fold_take_list(fold1
);
1103 list2
= isl_qpolynomial_fold_take_list(fold2
);
1104 list1
= isl_qpolynomial_list_concat(list1
, list2
);
1105 fold1
= isl_qpolynomial_fold_restore_list(fold1
, list1
);
1106 isl_qpolynomial_fold_free(fold2
);
1110 isl_qpolynomial_fold_free(fold1
);
1111 isl_qpolynomial_fold_free(fold2
);
1115 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_fold(
1116 __isl_take isl_pw_qpolynomial_fold
*pw1
,
1117 __isl_take isl_pw_qpolynomial_fold
*pw2
)
1120 struct isl_pw_qpolynomial_fold
*res
;
1126 isl_assert(pw1
->dim
->ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
1128 if (isl_pw_qpolynomial_fold_is_zero(pw1
)) {
1129 isl_pw_qpolynomial_fold_free(pw1
);
1133 if (isl_pw_qpolynomial_fold_is_zero(pw2
)) {
1134 isl_pw_qpolynomial_fold_free(pw2
);
1138 if (pw1
->type
!= pw2
->type
)
1139 isl_die(pw1
->dim
->ctx
, isl_error_invalid
,
1140 "fold types don't match", goto error
);
1142 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
1143 res
= isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pw1
->dim
),
1146 for (i
= 0; i
< pw1
->n
; ++i
) {
1147 set
= isl_set_copy(pw1
->p
[i
].set
);
1148 for (j
= 0; j
< pw2
->n
; ++j
) {
1149 struct isl_set
*common
;
1150 isl_qpolynomial_fold
*sum
;
1151 set
= isl_set_subtract(set
,
1152 isl_set_copy(pw2
->p
[j
].set
));
1153 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
1154 isl_set_copy(pw2
->p
[j
].set
));
1155 if (isl_set_plain_is_empty(common
)) {
1156 isl_set_free(common
);
1160 sum
= isl_qpolynomial_fold_fold_on_domain(common
,
1161 isl_qpolynomial_fold_copy(pw1
->p
[i
].fold
),
1162 isl_qpolynomial_fold_copy(pw2
->p
[j
].fold
));
1164 res
= isl_pw_qpolynomial_fold_add_piece(res
, common
, sum
);
1166 res
= isl_pw_qpolynomial_fold_add_piece(res
, set
,
1167 isl_qpolynomial_fold_copy(pw1
->p
[i
].fold
));
1170 for (j
= 0; j
< pw2
->n
; ++j
) {
1171 set
= isl_set_copy(pw2
->p
[j
].set
);
1172 for (i
= 0; i
< pw1
->n
; ++i
)
1173 set
= isl_set_subtract(set
, isl_set_copy(pw1
->p
[i
].set
));
1174 res
= isl_pw_qpolynomial_fold_add_piece(res
, set
,
1175 isl_qpolynomial_fold_copy(pw2
->p
[j
].fold
));
1178 isl_pw_qpolynomial_fold_free(pw1
);
1179 isl_pw_qpolynomial_fold_free(pw2
);
1183 isl_pw_qpolynomial_fold_free(pw1
);
1184 isl_pw_qpolynomial_fold_free(pw2
);
1188 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
1189 __isl_take isl_union_pw_qpolynomial_fold
*u
,
1190 __isl_take isl_pw_qpolynomial_fold
*part
)
1192 struct isl_hash_table_entry
*entry
;
1194 u
= isl_union_pw_qpolynomial_fold_cow(u
);
1198 if (isl_space_check_equal_params(part
->dim
, u
->space
) < 0)
1201 entry
= isl_union_pw_qpolynomial_fold_find_part_entry(u
, part
->dim
, 1);
1208 entry
->data
= isl_pw_qpolynomial_fold_fold(entry
->data
,
1209 isl_pw_qpolynomial_fold_copy(part
));
1212 isl_pw_qpolynomial_fold_free(part
);
1217 isl_pw_qpolynomial_fold_free(part
);
1218 isl_union_pw_qpolynomial_fold_free(u
);
1222 static isl_stat
fold_part(__isl_take isl_pw_qpolynomial_fold
*part
, void *user
)
1224 isl_union_pw_qpolynomial_fold
**u
;
1225 u
= (isl_union_pw_qpolynomial_fold
**)user
;
1227 *u
= isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(*u
, part
);
1232 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_fold(
1233 __isl_take isl_union_pw_qpolynomial_fold
*u1
,
1234 __isl_take isl_union_pw_qpolynomial_fold
*u2
)
1236 u1
= isl_union_pw_qpolynomial_fold_cow(u1
);
1241 if (isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(u2
,
1242 &fold_part
, &u1
) < 0)
1245 isl_union_pw_qpolynomial_fold_free(u2
);
1249 isl_union_pw_qpolynomial_fold_free(u1
);
1250 isl_union_pw_qpolynomial_fold_free(u2
);
1254 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_from_pw_qpolynomial(
1255 enum isl_fold type
, __isl_take isl_pw_qpolynomial
*pwqp
)
1258 isl_pw_qpolynomial_fold
*pwf
;
1263 pwf
= isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pwqp
->dim
),
1266 for (i
= 0; i
< pwqp
->n
; ++i
)
1267 pwf
= isl_pw_qpolynomial_fold_add_piece(pwf
,
1268 isl_set_copy(pwqp
->p
[i
].set
),
1269 isl_qpolynomial_fold_alloc(type
,
1270 isl_qpolynomial_copy(pwqp
->p
[i
].qp
)));
1272 isl_pw_qpolynomial_free(pwqp
);
1277 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_add(
1278 __isl_take isl_pw_qpolynomial_fold
*pwf1
,
1279 __isl_take isl_pw_qpolynomial_fold
*pwf2
)
1281 return isl_pw_qpolynomial_fold_union_add_(pwf1
, pwf2
);
1284 /* Compare two quasi-polynomial reductions.
1286 * Return -1 if "fold1" is "smaller" than "fold2", 1 if "fold1" is "greater"
1287 * than "fold2" and 0 if they are equal.
1289 int isl_qpolynomial_fold_plain_cmp(__isl_keep isl_qpolynomial_fold
*fold1
,
1290 __isl_keep isl_qpolynomial_fold
*fold2
)
1294 isl_qpolynomial_list
*list1
, *list2
;
1298 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1299 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1300 n1
= isl_qpolynomial_list_size(list1
);
1301 n2
= isl_qpolynomial_list_size(list2
);
1310 for (i
= 0; i
< n1
; ++i
) {
1312 isl_qpolynomial
*qp1
, *qp2
;
1314 qp1
= isl_qpolynomial_list_peek(list1
, i
);
1315 qp2
= isl_qpolynomial_list_peek(list2
, i
);
1316 cmp
= isl_qpolynomial_plain_cmp(qp1
, qp2
);
1324 /* Are the lists "list1" and "list2", both consisting of "n" elements
1325 * obviously equal to each other?
1327 static isl_bool
isl_qpolynomial_list_plain_is_equal(unsigned n
,
1328 isl_qpolynomial_list
*list1
, isl_qpolynomial_list
*list2
)
1332 for (i
= 0; i
< n
; ++i
) {
1334 isl_qpolynomial
*qp1
, *qp2
;
1336 qp1
= isl_qpolynomial_list_peek(list1
, i
);
1337 qp2
= isl_qpolynomial_list_peek(list2
, i
);
1338 eq
= isl_qpolynomial_plain_is_equal(qp1
, qp2
);
1343 return isl_bool_true
;
1346 /* Wrapper around isl_qpolynomial_plain_cmp for use
1347 * as a isl_qpolynomial_list_sort callback.
1349 static int qpolynomial_cmp(__isl_keep isl_qpolynomial
*a
,
1350 __isl_keep isl_qpolynomial
*b
, void *user
)
1352 return isl_qpolynomial_plain_cmp(a
, b
);
1355 isl_bool
isl_qpolynomial_fold_plain_is_equal(
1356 __isl_keep isl_qpolynomial_fold
*fold1
,
1357 __isl_keep isl_qpolynomial_fold
*fold2
)
1361 isl_qpolynomial_list
*list1
, *list2
;
1363 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1364 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1365 n1
= isl_qpolynomial_list_size(list1
);
1366 n2
= isl_qpolynomial_list_size(list2
);
1367 if (n1
< 0 || n2
< 0)
1368 return isl_bool_error
;
1371 return isl_bool_false
;
1373 list1
= isl_qpolynomial_list_copy(list1
);
1374 list1
= isl_qpolynomial_list_sort(list1
, &qpolynomial_cmp
, NULL
);
1375 list2
= isl_qpolynomial_list_copy(list2
);
1376 list2
= isl_qpolynomial_list_sort(list2
, &qpolynomial_cmp
, NULL
);
1377 equal
= isl_qpolynomial_list_plain_is_equal(n1
, list1
, list2
);
1378 isl_qpolynomial_list_free(list1
);
1379 isl_qpolynomial_list_free(list2
);
1383 __isl_give isl_val
*isl_qpolynomial_fold_eval(
1384 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_point
*pnt
)
1389 isl_qpolynomial
*qp
;
1390 isl_qpolynomial_list
*list
;
1394 ctx
= isl_point_get_ctx(pnt
);
1395 isl_assert(pnt
->dim
->ctx
, isl_space_is_equal(pnt
->dim
, fold
->dim
), goto error
);
1396 isl_assert(pnt
->dim
->ctx
,
1397 fold
->type
== isl_fold_max
|| fold
->type
== isl_fold_min
,
1400 list
= isl_qpolynomial_fold_peek_list(fold
);
1401 n
= isl_qpolynomial_list_size(list
);
1406 v
= isl_val_zero(ctx
);
1410 qp
= isl_qpolynomial_list_get_at(list
, 0);
1411 v
= isl_qpolynomial_eval(qp
, isl_point_copy(pnt
));
1412 for (i
= 1; i
< n
; ++i
) {
1415 qp
= isl_qpolynomial_list_get_at(list
, i
);
1416 v_i
= isl_qpolynomial_eval(qp
, isl_point_copy(pnt
));
1417 if (fold
->type
== isl_fold_max
)
1418 v
= isl_val_max(v
, v_i
);
1420 v
= isl_val_min(v
, v_i
);
1423 isl_qpolynomial_fold_free(fold
);
1424 isl_point_free(pnt
);
1428 isl_qpolynomial_fold_free(fold
);
1429 isl_point_free(pnt
);
1433 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold
*pwf
)
1438 for (i
= 0; i
< pwf
->n
; ++i
) {
1440 isl_qpolynomial_list
*list
;
1442 list
= isl_qpolynomial_fold_peek_list(pwf
->p
[i
].fold
);
1443 n_i
= isl_qpolynomial_list_size(list
);
1445 return isl_size_error
;
1453 __isl_give isl_val
*isl_qpolynomial_fold_opt_on_domain(
1454 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_set
*set
, int max
)
1459 isl_qpolynomial
*qp
;
1460 isl_qpolynomial_list
*list
;
1462 list
= isl_qpolynomial_fold_peek_list(fold
);
1463 n
= isl_qpolynomial_list_size(list
);
1468 opt
= isl_val_zero(isl_set_get_ctx(set
));
1470 isl_qpolynomial_fold_free(fold
);
1474 qp
= isl_qpolynomial_list_get_at(list
, 0);
1475 opt
= isl_qpolynomial_opt_on_domain(qp
, isl_set_copy(set
), max
);
1476 for (i
= 1; i
< n
; ++i
) {
1479 qp
= isl_qpolynomial_list_get_at(list
, i
);
1480 opt_i
= isl_qpolynomial_opt_on_domain(qp
,
1481 isl_set_copy(set
), max
);
1483 opt
= isl_val_max(opt
, opt_i
);
1485 opt
= isl_val_min(opt
, opt_i
);
1489 isl_qpolynomial_fold_free(fold
);
1494 isl_qpolynomial_fold_free(fold
);
1498 /* Check whether for each quasi-polynomial in "fold2" there is
1499 * a quasi-polynomial in "fold1" that dominates it on "set".
1501 static isl_bool
qpolynomial_fold_covers_on_domain(__isl_keep isl_set
*set
,
1502 __isl_keep isl_qpolynomial_fold
*fold1
,
1503 __isl_keep isl_qpolynomial_fold
*fold2
)
1508 isl_qpolynomial_list
*list1
, *list2
;
1510 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1511 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1512 n1
= isl_qpolynomial_list_size(list1
);
1513 n2
= isl_qpolynomial_list_size(list2
);
1514 if (!set
|| n1
< 0 || n2
< 0)
1515 return isl_bool_error
;
1517 covers
= fold1
->type
== isl_fold_max
? 1 : -1;
1519 for (i
= 0; i
< n2
; ++i
) {
1520 for (j
= 0; j
< n1
; ++j
) {
1521 isl_qpolynomial
*qp1
, *qp2
, *d
;
1524 qp1
= isl_qpolynomial_list_get_at(list1
, j
);
1525 qp2
= isl_qpolynomial_list_get_at(list2
, i
);
1526 d
= isl_qpolynomial_sub(qp1
, qp2
);
1527 sgn
= isl_qpolynomial_sign(set
, d
);
1528 isl_qpolynomial_free(d
);
1533 return isl_bool_false
;
1536 return isl_bool_true
;
1539 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
1540 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
1543 isl_bool
isl_pw_qpolynomial_fold_covers(
1544 __isl_keep isl_pw_qpolynomial_fold
*pwf1
,
1545 __isl_keep isl_pw_qpolynomial_fold
*pwf2
)
1548 isl_set
*dom1
, *dom2
;
1552 return isl_bool_error
;
1555 return isl_bool_true
;
1557 return isl_bool_false
;
1559 dom1
= isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1
));
1560 dom2
= isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2
));
1561 is_subset
= isl_set_is_subset(dom2
, dom1
);
1565 if (is_subset
< 0 || !is_subset
)
1568 for (i
= 0; i
< pwf2
->n
; ++i
) {
1569 for (j
= 0; j
< pwf1
->n
; ++j
) {
1574 common
= isl_set_intersect(isl_set_copy(pwf1
->p
[j
].set
),
1575 isl_set_copy(pwf2
->p
[i
].set
));
1576 is_empty
= isl_set_is_empty(common
);
1577 if (is_empty
< 0 || is_empty
) {
1578 isl_set_free(common
);
1580 return isl_bool_error
;
1583 covers
= qpolynomial_fold_covers_on_domain(common
,
1584 pwf1
->p
[j
].fold
, pwf2
->p
[i
].fold
);
1585 isl_set_free(common
);
1586 if (covers
< 0 || !covers
)
1591 return isl_bool_true
;
1594 /* isl_qpolynomial_list_map callback that calls
1595 * isl_qpolynomial_morph_domain on "qp".
1597 static __isl_give isl_qpolynomial
*morph_domain(
1598 __isl_take isl_qpolynomial
*qp
, void *user
)
1600 isl_morph
*morph
= user
;
1602 return isl_qpolynomial_morph_domain(qp
, isl_morph_copy(morph
));
1605 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_morph_domain(
1606 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_morph
*morph
)
1609 isl_qpolynomial_list
*list
;
1611 space
= isl_qpolynomial_fold_peek_domain_space(fold
);
1612 if (isl_morph_check_applies(morph
, space
) < 0)
1615 list
= isl_qpolynomial_fold_take_list(fold
);
1616 list
= isl_qpolynomial_list_map(list
, &morph_domain
, morph
);
1617 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1619 space
= isl_morph_get_ran_space(morph
);
1620 isl_space_free(isl_qpolynomial_fold_take_domain_space(fold
));
1621 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1623 isl_morph_free(morph
);
1627 isl_qpolynomial_fold_free(fold
);
1628 isl_morph_free(morph
);
1632 enum isl_fold
isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold
*fold
)
1635 return isl_fold_error
;
1639 /* Return the type of this piecewise quasipolynomial reduction.
1641 enum isl_fold
isl_pw_qpolynomial_fold_get_type(
1642 __isl_keep isl_pw_qpolynomial_fold
*pwf
)
1645 return isl_fold_error
;
1649 enum isl_fold
isl_union_pw_qpolynomial_fold_get_type(
1650 __isl_keep isl_union_pw_qpolynomial_fold
*upwf
)
1653 return isl_fold_error
;
1657 /* isl_qpolynomial_list_map callback that calls
1658 * isl_qpolynomial_lift on "qp".
1660 static __isl_give isl_qpolynomial
*lift(__isl_take isl_qpolynomial
*qp
,
1663 isl_space
*space
= user
;
1665 return isl_qpolynomial_lift(qp
, isl_space_copy(space
));
1668 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_lift(
1669 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_space
*space
)
1671 isl_qpolynomial_list
*list
;
1673 if (!fold
|| !space
)
1676 if (isl_space_is_equal(fold
->dim
, space
)) {
1677 isl_space_free(space
);
1681 list
= isl_qpolynomial_fold_take_list(fold
);
1682 list
= isl_qpolynomial_list_map(list
, &lift
, space
);
1683 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1685 isl_space_free(isl_qpolynomial_fold_take_domain_space(fold
));
1686 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1690 isl_qpolynomial_fold_free(fold
);
1691 isl_space_free(space
);
1695 isl_stat
isl_qpolynomial_fold_foreach_qpolynomial(
1696 __isl_keep isl_qpolynomial_fold
*fold
,
1697 isl_stat (*fn
)(__isl_take isl_qpolynomial
*qp
, void *user
), void *user
)
1699 isl_qpolynomial_list
*list
;
1701 list
= isl_qpolynomial_fold_peek_list(fold
);
1702 return isl_qpolynomial_list_foreach(list
, fn
, user
);
1705 /* Internal data structure for isl_qpolynomial_fold_move_dims
1706 * representing its arguments.
1708 struct isl_fold_move_dims_data
{
1709 enum isl_dim_type dst_type
;
1711 enum isl_dim_type src_type
;
1716 /* isl_qpolynomial_list_map callback for calling
1717 * isl_qpolynomial_move_dims on "qp".
1719 static __isl_give isl_qpolynomial
*move_dims(__isl_take isl_qpolynomial
*qp
,
1722 struct isl_fold_move_dims_data
*data
= user
;
1724 qp
= isl_qpolynomial_move_dims(qp
, data
->dst_type
, data
->dst_pos
,
1725 data
->src_type
, data
->src_pos
, data
->n
);
1729 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_move_dims(
1730 __isl_take isl_qpolynomial_fold
*fold
,
1731 enum isl_dim_type dst_type
, unsigned dst_pos
,
1732 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1734 struct isl_fold_move_dims_data data
=
1735 { dst_type
, dst_pos
, src_type
, src_pos
, n
};
1736 enum isl_dim_type set_src_type
, set_dst_type
;
1738 isl_qpolynomial_list
*list
;
1743 fold
= isl_qpolynomial_fold_cow(fold
);
1747 set_src_type
= domain_type(src_type
);
1748 set_dst_type
= domain_type(dst_type
);
1750 list
= isl_qpolynomial_fold_take_list(fold
);
1751 list
= isl_qpolynomial_list_map(list
, &move_dims
, &data
);
1752 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1754 space
= isl_qpolynomial_fold_take_domain_space(fold
);
1755 space
= isl_space_move_dims(space
, set_dst_type
, dst_pos
,
1756 set_src_type
, src_pos
, n
);
1757 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1762 /* Internal data structure for isl_qpolynomial_fold_substitute
1763 * representing its arguments.
1765 struct isl_fold_substitute
{
1766 enum isl_dim_type type
;
1769 isl_qpolynomial
**subs
;
1772 /* isl_qpolynomial_list_map callback for calling
1773 * isl_qpolynomial_substitute on "qp".
1775 static __isl_give isl_qpolynomial
*substitute(__isl_take isl_qpolynomial
*qp
,
1778 struct isl_fold_substitute
*data
= user
;
1780 qp
= isl_qpolynomial_substitute(qp
,
1781 data
->type
, data
->first
, data
->n
, data
->subs
);
1785 /* For each 0 <= i < "n", replace variable "first" + i of type "type"
1786 * in fold->qp[k] by subs[i].
1788 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_substitute(
1789 __isl_take isl_qpolynomial_fold
*fold
,
1790 enum isl_dim_type type
, unsigned first
, unsigned n
,
1791 __isl_keep isl_qpolynomial
**subs
)
1793 struct isl_fold_substitute data
= { type
, first
, n
, subs
};
1794 isl_qpolynomial_list
*list
;
1799 list
= isl_qpolynomial_fold_take_list(fold
);
1800 list
= isl_qpolynomial_list_map(list
, &substitute
, &data
);
1801 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1806 static isl_stat
add_pwqp(__isl_take isl_pw_qpolynomial
*pwqp
, void *user
)
1808 isl_pw_qpolynomial_fold
*pwf
;
1809 isl_union_pw_qpolynomial_fold
**upwf
;
1810 struct isl_hash_table_entry
*entry
;
1812 upwf
= (isl_union_pw_qpolynomial_fold
**)user
;
1814 entry
= isl_union_pw_qpolynomial_fold_find_part_entry(*upwf
,
1819 pwf
= isl_pw_qpolynomial_fold_from_pw_qpolynomial((*upwf
)->type
, pwqp
);
1823 entry
->data
= isl_pw_qpolynomial_fold_add(entry
->data
, pwf
);
1825 return isl_stat_error
;
1826 if (isl_pw_qpolynomial_fold_is_zero(entry
->data
))
1827 *upwf
= isl_union_pw_qpolynomial_fold_remove_part_entry(
1833 isl_pw_qpolynomial_free(pwqp
);
1834 return isl_stat_error
;
1837 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
1838 __isl_take isl_union_pw_qpolynomial_fold
*upwf
,
1839 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1841 upwf
= isl_union_pw_qpolynomial_fold_align_params(upwf
,
1842 isl_union_pw_qpolynomial_get_space(upwqp
));
1843 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1844 isl_union_pw_qpolynomial_fold_get_space(upwf
));
1846 upwf
= isl_union_pw_qpolynomial_fold_cow(upwf
);
1847 if (!upwf
|| !upwqp
)
1850 if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp
, &add_pwqp
,
1854 isl_union_pw_qpolynomial_free(upwqp
);
1858 isl_union_pw_qpolynomial_fold_free(upwf
);
1859 isl_union_pw_qpolynomial_free(upwqp
);
1863 static isl_bool
join_compatible(__isl_keep isl_space
*space1
,
1864 __isl_keep isl_space
*space2
)
1867 m
= isl_space_has_equal_params(space1
, space2
);
1870 return isl_space_tuple_is_equal(space1
, isl_dim_out
,
1871 space2
, isl_dim_in
);
1874 /* Compute the intersection of the range of the map and the domain
1875 * of the piecewise quasipolynomial reduction and then compute a bound
1876 * on the associated quasipolynomial reduction over all elements
1877 * in this intersection.
1879 * We first introduce some unconstrained dimensions in the
1880 * piecewise quasipolynomial, intersect the resulting domain
1881 * with the wrapped map and the compute the sum.
1883 __isl_give isl_pw_qpolynomial_fold
*isl_map_apply_pw_qpolynomial_fold(
1884 __isl_take isl_map
*map
, __isl_take isl_pw_qpolynomial_fold
*pwf
,
1889 isl_space
*map_space
;
1890 isl_space
*pwf_space
;
1894 ctx
= isl_map_get_ctx(map
);
1898 map_space
= isl_map_get_space(map
);
1899 pwf_space
= isl_pw_qpolynomial_fold_get_space(pwf
);
1900 ok
= join_compatible(map_space
, pwf_space
);
1901 isl_space_free(map_space
);
1902 isl_space_free(pwf_space
);
1906 isl_die(ctx
, isl_error_invalid
, "incompatible dimensions",
1909 n_in
= isl_map_dim(map
, isl_dim_in
);
1912 pwf
= isl_pw_qpolynomial_fold_insert_dims(pwf
, isl_dim_in
, 0, n_in
);
1914 dom
= isl_map_wrap(map
);
1915 pwf
= isl_pw_qpolynomial_fold_reset_domain_space(pwf
,
1916 isl_set_get_space(dom
));
1918 pwf
= isl_pw_qpolynomial_fold_intersect_domain(pwf
, dom
);
1919 pwf
= isl_pw_qpolynomial_fold_bound(pwf
, tight
);
1924 isl_pw_qpolynomial_fold_free(pwf
);
1928 __isl_give isl_pw_qpolynomial_fold
*isl_set_apply_pw_qpolynomial_fold(
1929 __isl_take isl_set
*set
, __isl_take isl_pw_qpolynomial_fold
*pwf
,
1932 return isl_map_apply_pw_qpolynomial_fold(set
, pwf
, tight
);
1935 struct isl_apply_fold_data
{
1936 isl_union_pw_qpolynomial_fold
*upwf
;
1937 isl_union_pw_qpolynomial_fold
*res
;
1942 static isl_stat
pw_qpolynomial_fold_apply(
1943 __isl_take isl_pw_qpolynomial_fold
*pwf
, void *user
)
1947 struct isl_apply_fold_data
*data
= user
;
1950 map_dim
= isl_map_get_space(data
->map
);
1951 pwf_dim
= isl_pw_qpolynomial_fold_get_space(pwf
);
1952 ok
= join_compatible(map_dim
, pwf_dim
);
1953 isl_space_free(map_dim
);
1954 isl_space_free(pwf_dim
);
1957 return isl_stat_error
;
1959 pwf
= isl_map_apply_pw_qpolynomial_fold(isl_map_copy(data
->map
),
1960 pwf
, data
->tight
? &data
->tight
: NULL
);
1961 data
->res
= isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
1964 isl_pw_qpolynomial_fold_free(pwf
);
1969 static isl_stat
map_apply(__isl_take isl_map
*map
, void *user
)
1971 struct isl_apply_fold_data
*data
= user
;
1975 r
= isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
1976 data
->upwf
, &pw_qpolynomial_fold_apply
, data
);
1982 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_map_apply_union_pw_qpolynomial_fold(
1983 __isl_take isl_union_map
*umap
,
1984 __isl_take isl_union_pw_qpolynomial_fold
*upwf
, isl_bool
*tight
)
1988 struct isl_apply_fold_data data
;
1990 upwf
= isl_union_pw_qpolynomial_fold_align_params(upwf
,
1991 isl_union_map_get_space(umap
));
1992 umap
= isl_union_map_align_params(umap
,
1993 isl_union_pw_qpolynomial_fold_get_space(upwf
));
1996 data
.tight
= tight
? isl_bool_true
: isl_bool_false
;
1997 space
= isl_union_pw_qpolynomial_fold_get_space(upwf
);
1998 type
= isl_union_pw_qpolynomial_fold_get_type(upwf
);
1999 data
.res
= isl_union_pw_qpolynomial_fold_zero(space
, type
);
2000 if (isl_union_map_foreach_map(umap
, &map_apply
, &data
) < 0)
2003 isl_union_map_free(umap
);
2004 isl_union_pw_qpolynomial_fold_free(upwf
);
2007 *tight
= data
.tight
;
2011 isl_union_map_free(umap
);
2012 isl_union_pw_qpolynomial_fold_free(upwf
);
2013 isl_union_pw_qpolynomial_fold_free(data
.res
);
2017 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_set_apply_union_pw_qpolynomial_fold(
2018 __isl_take isl_union_set
*uset
,
2019 __isl_take isl_union_pw_qpolynomial_fold
*upwf
, isl_bool
*tight
)
2021 return isl_union_map_apply_union_pw_qpolynomial_fold(uset
, upwf
, tight
);
2024 /* isl_qpolynomial_list_map callback for calling
2025 * isl_qpolynomial_realign_domain on "qp".
2027 static __isl_give isl_qpolynomial
*realign_domain(
2028 __isl_take isl_qpolynomial
*qp
, void *user
)
2030 isl_reordering
*r
= user
;
2032 qp
= isl_qpolynomial_realign_domain(qp
, isl_reordering_copy(r
));
2036 /* Reorder the dimension of "fold" according to the given reordering.
2038 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_realign_domain(
2039 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_reordering
*r
)
2042 isl_qpolynomial_list
*list
;
2044 list
= isl_qpolynomial_fold_take_list(fold
);
2045 list
= isl_qpolynomial_list_map(list
, &realign_domain
, r
);
2046 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2048 space
= isl_reordering_get_space(r
);
2049 fold
= isl_qpolynomial_fold_reset_domain_space(fold
, space
);
2051 isl_reordering_free(r
);
2056 /* isl_qpolynomial_list_map callback for calling
2057 * isl_qpolynomial_mul_isl_int on "qp".
2059 static __isl_give isl_qpolynomial
*mul_int(__isl_take isl_qpolynomial
*qp
,
2064 qp
= isl_qpolynomial_mul_isl_int(qp
, *v
);
2068 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_mul_isl_int(
2069 __isl_take isl_qpolynomial_fold
*fold
, isl_int v
)
2071 isl_qpolynomial_list
*list
;
2073 if (isl_int_is_one(v
))
2075 if (fold
&& isl_int_is_zero(v
)) {
2076 isl_qpolynomial_fold
*zero
;
2077 isl_space
*space
= isl_space_copy(fold
->dim
);
2078 zero
= isl_qpolynomial_fold_empty(fold
->type
, space
);
2079 isl_qpolynomial_fold_free(fold
);
2083 fold
= isl_qpolynomial_fold_cow(fold
);
2087 if (isl_int_is_neg(v
))
2088 fold
->type
= isl_fold_type_negate(fold
->type
);
2090 list
= isl_qpolynomial_fold_take_list(fold
);
2091 list
= isl_qpolynomial_list_map(list
, &mul_int
, &v
);
2092 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2097 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale(
2098 __isl_take isl_qpolynomial_fold
*fold
, isl_int v
)
2100 return isl_qpolynomial_fold_mul_isl_int(fold
, v
);
2103 /* isl_qpolynomial_list_map callback for calling
2104 * isl_qpolynomial_scale_val on "qp".
2106 static __isl_give isl_qpolynomial
*scale_val(__isl_take isl_qpolynomial
*qp
,
2111 qp
= isl_qpolynomial_scale_val(qp
, isl_val_copy(v
));
2115 /* Multiply "fold" by "v".
2117 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale_val(
2118 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_val
*v
)
2120 isl_qpolynomial_list
*list
;
2125 if (isl_val_is_one(v
)) {
2129 if (isl_val_is_zero(v
)) {
2130 isl_qpolynomial_fold
*zero
;
2131 isl_space
*space
= isl_qpolynomial_fold_get_domain_space(fold
);
2132 zero
= isl_qpolynomial_fold_empty(fold
->type
, space
);
2133 isl_qpolynomial_fold_free(fold
);
2137 if (!isl_val_is_rat(v
))
2138 isl_die(isl_qpolynomial_fold_get_ctx(fold
), isl_error_invalid
,
2139 "expecting rational factor", goto error
);
2141 fold
= isl_qpolynomial_fold_cow(fold
);
2145 if (isl_val_is_neg(v
))
2146 fold
->type
= isl_fold_type_negate(fold
->type
);
2148 list
= isl_qpolynomial_fold_take_list(fold
);
2149 list
= isl_qpolynomial_list_map(list
, &scale_val
, v
);
2150 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2156 isl_qpolynomial_fold_free(fold
);
2160 /* Divide "fold" by "v".
2162 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale_down_val(
2163 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_val
*v
)
2168 if (isl_val_is_one(v
)) {
2172 if (!isl_val_is_rat(v
))
2173 isl_die(isl_qpolynomial_fold_get_ctx(fold
), isl_error_invalid
,
2174 "expecting rational factor", goto error
);
2175 if (isl_val_is_zero(v
))
2176 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
2177 "cannot scale down by zero", goto error
);
2179 return isl_qpolynomial_fold_scale_val(fold
, isl_val_inv(v
));
2182 isl_qpolynomial_fold_free(fold
);