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_eval.c>
955 #include <isl_pw_insert_dims_templ.c>
956 #include <isl_pw_lift_templ.c>
957 #include <isl_pw_morph_templ.c>
958 #include <isl_pw_move_dims_templ.c>
959 #include <isl_pw_opt_templ.c>
962 #define BASE pw_qpolynomial_fold
966 #include <isl_union_single.c>
967 #include <isl_union_eval.c>
969 /* Construct a new reduction of the given type and space
970 * with an empty list of polynomials.
972 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_empty(enum isl_fold type
,
973 __isl_take isl_space
*space
)
976 isl_qpolynomial_list
*list
;
980 ctx
= isl_space_get_ctx(space
);
981 list
= isl_qpolynomial_list_alloc(ctx
, 0);
982 return qpolynomial_fold_alloc(type
, space
, list
);
985 /* Construct a new reduction of the given type and
986 * a single given polynomial.
988 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_alloc(
989 enum isl_fold type
, __isl_take isl_qpolynomial
*qp
)
992 isl_qpolynomial_list
*list
;
994 space
= isl_qpolynomial_get_domain_space(qp
);
995 list
= isl_qpolynomial_list_from_qpolynomial(qp
);
996 return qpolynomial_fold_alloc(type
, space
, list
);
999 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_copy(
1000 __isl_keep isl_qpolynomial_fold
*fold
)
1009 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_dup(
1010 __isl_keep isl_qpolynomial_fold
*fold
)
1014 isl_qpolynomial_list
*list
;
1016 type
= isl_qpolynomial_fold_get_type(fold
);
1017 space
= isl_qpolynomial_fold_get_domain_space(fold
);
1018 list
= isl_qpolynomial_fold_get_list(fold
);
1019 return qpolynomial_fold_alloc(type
, space
, list
);
1022 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_cow(
1023 __isl_take isl_qpolynomial_fold
*fold
)
1031 return isl_qpolynomial_fold_dup(fold
);
1034 __isl_null isl_qpolynomial_fold
*isl_qpolynomial_fold_free(
1035 __isl_take isl_qpolynomial_fold
*fold
)
1039 if (--fold
->ref
> 0)
1042 isl_qpolynomial_list_free(fold
->list
);
1043 isl_space_free(fold
->dim
);
1049 isl_bool
isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold
*fold
)
1052 isl_qpolynomial_list
*list
;
1054 list
= isl_qpolynomial_fold_peek_list(fold
);
1055 n
= isl_qpolynomial_list_size(list
);
1057 return isl_bool_error
;
1059 return isl_bool_ok(n
== 0);
1062 /* Does "fold" represent max(NaN) or min(NaN)?
1064 isl_bool
isl_qpolynomial_fold_is_nan(__isl_keep isl_qpolynomial_fold
*fold
)
1067 isl_qpolynomial
*qp
;
1068 isl_qpolynomial_list
*list
;
1070 list
= isl_qpolynomial_fold_peek_list(fold
);
1071 n
= isl_qpolynomial_list_size(list
);
1073 return isl_bool_error
;
1075 return isl_bool_false
;
1076 qp
= isl_qpolynomial_list_peek(list
, 0);
1077 return isl_qpolynomial_is_nan(qp
);
1080 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_fold(
1081 __isl_take isl_qpolynomial_fold
*fold1
,
1082 __isl_take isl_qpolynomial_fold
*fold2
)
1084 isl_qpolynomial_list
*list1
, *list2
;
1086 if (isl_qpolynomial_fold_check_equal_type(fold1
, fold2
) < 0)
1088 if (isl_qpolynomial_fold_check_equal_space(fold1
, fold2
) < 0)
1091 if (isl_qpolynomial_fold_is_empty(fold1
)) {
1092 isl_qpolynomial_fold_free(fold1
);
1096 if (isl_qpolynomial_fold_is_empty(fold2
)) {
1097 isl_qpolynomial_fold_free(fold2
);
1101 list1
= isl_qpolynomial_fold_take_list(fold1
);
1102 list2
= isl_qpolynomial_fold_take_list(fold2
);
1103 list1
= isl_qpolynomial_list_concat(list1
, list2
);
1104 fold1
= isl_qpolynomial_fold_restore_list(fold1
, list1
);
1105 isl_qpolynomial_fold_free(fold2
);
1109 isl_qpolynomial_fold_free(fold1
);
1110 isl_qpolynomial_fold_free(fold2
);
1114 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_fold(
1115 __isl_take isl_pw_qpolynomial_fold
*pw1
,
1116 __isl_take isl_pw_qpolynomial_fold
*pw2
)
1119 struct isl_pw_qpolynomial_fold
*res
;
1125 isl_assert(pw1
->dim
->ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
1127 if (isl_pw_qpolynomial_fold_is_zero(pw1
)) {
1128 isl_pw_qpolynomial_fold_free(pw1
);
1132 if (isl_pw_qpolynomial_fold_is_zero(pw2
)) {
1133 isl_pw_qpolynomial_fold_free(pw2
);
1137 if (pw1
->type
!= pw2
->type
)
1138 isl_die(pw1
->dim
->ctx
, isl_error_invalid
,
1139 "fold types don't match", goto error
);
1141 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
1142 res
= isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pw1
->dim
),
1145 for (i
= 0; i
< pw1
->n
; ++i
) {
1146 set
= isl_set_copy(pw1
->p
[i
].set
);
1147 for (j
= 0; j
< pw2
->n
; ++j
) {
1148 struct isl_set
*common
;
1149 isl_qpolynomial_fold
*sum
;
1150 set
= isl_set_subtract(set
,
1151 isl_set_copy(pw2
->p
[j
].set
));
1152 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
1153 isl_set_copy(pw2
->p
[j
].set
));
1154 if (isl_set_plain_is_empty(common
)) {
1155 isl_set_free(common
);
1159 sum
= isl_qpolynomial_fold_fold_on_domain(common
,
1160 isl_qpolynomial_fold_copy(pw1
->p
[i
].fold
),
1161 isl_qpolynomial_fold_copy(pw2
->p
[j
].fold
));
1163 res
= isl_pw_qpolynomial_fold_add_piece(res
, common
, sum
);
1165 res
= isl_pw_qpolynomial_fold_add_piece(res
, set
,
1166 isl_qpolynomial_fold_copy(pw1
->p
[i
].fold
));
1169 for (j
= 0; j
< pw2
->n
; ++j
) {
1170 set
= isl_set_copy(pw2
->p
[j
].set
);
1171 for (i
= 0; i
< pw1
->n
; ++i
)
1172 set
= isl_set_subtract(set
, isl_set_copy(pw1
->p
[i
].set
));
1173 res
= isl_pw_qpolynomial_fold_add_piece(res
, set
,
1174 isl_qpolynomial_fold_copy(pw2
->p
[j
].fold
));
1177 isl_pw_qpolynomial_fold_free(pw1
);
1178 isl_pw_qpolynomial_fold_free(pw2
);
1182 isl_pw_qpolynomial_fold_free(pw1
);
1183 isl_pw_qpolynomial_fold_free(pw2
);
1187 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
1188 __isl_take isl_union_pw_qpolynomial_fold
*u
,
1189 __isl_take isl_pw_qpolynomial_fold
*part
)
1191 struct isl_hash_table_entry
*entry
;
1193 u
= isl_union_pw_qpolynomial_fold_cow(u
);
1197 if (isl_space_check_equal_params(part
->dim
, u
->space
) < 0)
1200 entry
= isl_union_pw_qpolynomial_fold_find_part_entry(u
, part
->dim
, 1);
1207 entry
->data
= isl_pw_qpolynomial_fold_fold(entry
->data
,
1208 isl_pw_qpolynomial_fold_copy(part
));
1211 isl_pw_qpolynomial_fold_free(part
);
1216 isl_pw_qpolynomial_fold_free(part
);
1217 isl_union_pw_qpolynomial_fold_free(u
);
1221 static isl_stat
fold_part(__isl_take isl_pw_qpolynomial_fold
*part
, void *user
)
1223 isl_union_pw_qpolynomial_fold
**u
;
1224 u
= (isl_union_pw_qpolynomial_fold
**)user
;
1226 *u
= isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(*u
, part
);
1231 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_fold(
1232 __isl_take isl_union_pw_qpolynomial_fold
*u1
,
1233 __isl_take isl_union_pw_qpolynomial_fold
*u2
)
1235 u1
= isl_union_pw_qpolynomial_fold_cow(u1
);
1240 if (isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(u2
,
1241 &fold_part
, &u1
) < 0)
1244 isl_union_pw_qpolynomial_fold_free(u2
);
1248 isl_union_pw_qpolynomial_fold_free(u1
);
1249 isl_union_pw_qpolynomial_fold_free(u2
);
1253 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_from_pw_qpolynomial(
1254 enum isl_fold type
, __isl_take isl_pw_qpolynomial
*pwqp
)
1257 isl_pw_qpolynomial_fold
*pwf
;
1262 pwf
= isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pwqp
->dim
),
1265 for (i
= 0; i
< pwqp
->n
; ++i
)
1266 pwf
= isl_pw_qpolynomial_fold_add_piece(pwf
,
1267 isl_set_copy(pwqp
->p
[i
].set
),
1268 isl_qpolynomial_fold_alloc(type
,
1269 isl_qpolynomial_copy(pwqp
->p
[i
].qp
)));
1271 isl_pw_qpolynomial_free(pwqp
);
1276 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_add(
1277 __isl_take isl_pw_qpolynomial_fold
*pwf1
,
1278 __isl_take isl_pw_qpolynomial_fold
*pwf2
)
1280 return isl_pw_qpolynomial_fold_union_add_(pwf1
, pwf2
);
1283 /* Compare two quasi-polynomial reductions.
1285 * Return -1 if "fold1" is "smaller" than "fold2", 1 if "fold1" is "greater"
1286 * than "fold2" and 0 if they are equal.
1288 int isl_qpolynomial_fold_plain_cmp(__isl_keep isl_qpolynomial_fold
*fold1
,
1289 __isl_keep isl_qpolynomial_fold
*fold2
)
1293 isl_qpolynomial_list
*list1
, *list2
;
1297 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1298 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1299 n1
= isl_qpolynomial_list_size(list1
);
1300 n2
= isl_qpolynomial_list_size(list2
);
1309 for (i
= 0; i
< n1
; ++i
) {
1311 isl_qpolynomial
*qp1
, *qp2
;
1313 qp1
= isl_qpolynomial_list_peek(list1
, i
);
1314 qp2
= isl_qpolynomial_list_peek(list2
, i
);
1315 cmp
= isl_qpolynomial_plain_cmp(qp1
, qp2
);
1323 /* Are the lists "list1" and "list2", both consisting of "n" elements
1324 * obviously equal to each other?
1326 static isl_bool
isl_qpolynomial_list_plain_is_equal(unsigned n
,
1327 isl_qpolynomial_list
*list1
, isl_qpolynomial_list
*list2
)
1331 for (i
= 0; i
< n
; ++i
) {
1333 isl_qpolynomial
*qp1
, *qp2
;
1335 qp1
= isl_qpolynomial_list_peek(list1
, i
);
1336 qp2
= isl_qpolynomial_list_peek(list2
, i
);
1337 eq
= isl_qpolynomial_plain_is_equal(qp1
, qp2
);
1342 return isl_bool_true
;
1345 /* Wrapper around isl_qpolynomial_plain_cmp for use
1346 * as a isl_qpolynomial_list_sort callback.
1348 static int qpolynomial_cmp(__isl_keep isl_qpolynomial
*a
,
1349 __isl_keep isl_qpolynomial
*b
, void *user
)
1351 return isl_qpolynomial_plain_cmp(a
, b
);
1354 isl_bool
isl_qpolynomial_fold_plain_is_equal(
1355 __isl_keep isl_qpolynomial_fold
*fold1
,
1356 __isl_keep isl_qpolynomial_fold
*fold2
)
1360 isl_qpolynomial_list
*list1
, *list2
;
1362 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1363 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1364 n1
= isl_qpolynomial_list_size(list1
);
1365 n2
= isl_qpolynomial_list_size(list2
);
1366 if (n1
< 0 || n2
< 0)
1367 return isl_bool_error
;
1370 return isl_bool_false
;
1372 list1
= isl_qpolynomial_list_copy(list1
);
1373 list1
= isl_qpolynomial_list_sort(list1
, &qpolynomial_cmp
, NULL
);
1374 list2
= isl_qpolynomial_list_copy(list2
);
1375 list2
= isl_qpolynomial_list_sort(list2
, &qpolynomial_cmp
, NULL
);
1376 equal
= isl_qpolynomial_list_plain_is_equal(n1
, list1
, list2
);
1377 isl_qpolynomial_list_free(list1
);
1378 isl_qpolynomial_list_free(list2
);
1382 __isl_give isl_val
*isl_qpolynomial_fold_eval(
1383 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_point
*pnt
)
1388 isl_qpolynomial
*qp
;
1389 isl_qpolynomial_list
*list
;
1393 ctx
= isl_point_get_ctx(pnt
);
1394 isl_assert(pnt
->dim
->ctx
, isl_space_is_equal(pnt
->dim
, fold
->dim
), goto error
);
1395 isl_assert(pnt
->dim
->ctx
,
1396 fold
->type
== isl_fold_max
|| fold
->type
== isl_fold_min
,
1399 list
= isl_qpolynomial_fold_peek_list(fold
);
1400 n
= isl_qpolynomial_list_size(list
);
1405 v
= isl_val_zero(ctx
);
1409 qp
= isl_qpolynomial_list_get_at(list
, 0);
1410 v
= isl_qpolynomial_eval(qp
, isl_point_copy(pnt
));
1411 for (i
= 1; i
< n
; ++i
) {
1414 qp
= isl_qpolynomial_list_get_at(list
, i
);
1415 v_i
= isl_qpolynomial_eval(qp
, isl_point_copy(pnt
));
1416 if (fold
->type
== isl_fold_max
)
1417 v
= isl_val_max(v
, v_i
);
1419 v
= isl_val_min(v
, v_i
);
1422 isl_qpolynomial_fold_free(fold
);
1423 isl_point_free(pnt
);
1427 isl_qpolynomial_fold_free(fold
);
1428 isl_point_free(pnt
);
1432 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold
*pwf
)
1437 for (i
= 0; i
< pwf
->n
; ++i
) {
1439 isl_qpolynomial_list
*list
;
1441 list
= isl_qpolynomial_fold_peek_list(pwf
->p
[i
].fold
);
1442 n_i
= isl_qpolynomial_list_size(list
);
1444 return isl_size_error
;
1452 __isl_give isl_val
*isl_qpolynomial_fold_opt_on_domain(
1453 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_set
*set
, int max
)
1458 isl_qpolynomial
*qp
;
1459 isl_qpolynomial_list
*list
;
1461 list
= isl_qpolynomial_fold_peek_list(fold
);
1462 n
= isl_qpolynomial_list_size(list
);
1467 opt
= isl_val_zero(isl_set_get_ctx(set
));
1469 isl_qpolynomial_fold_free(fold
);
1473 qp
= isl_qpolynomial_list_get_at(list
, 0);
1474 opt
= isl_qpolynomial_opt_on_domain(qp
, isl_set_copy(set
), max
);
1475 for (i
= 1; i
< n
; ++i
) {
1478 qp
= isl_qpolynomial_list_get_at(list
, i
);
1479 opt_i
= isl_qpolynomial_opt_on_domain(qp
,
1480 isl_set_copy(set
), max
);
1482 opt
= isl_val_max(opt
, opt_i
);
1484 opt
= isl_val_min(opt
, opt_i
);
1488 isl_qpolynomial_fold_free(fold
);
1493 isl_qpolynomial_fold_free(fold
);
1497 /* Check whether for each quasi-polynomial in "fold2" there is
1498 * a quasi-polynomial in "fold1" that dominates it on "set".
1500 static isl_bool
qpolynomial_fold_covers_on_domain(__isl_keep isl_set
*set
,
1501 __isl_keep isl_qpolynomial_fold
*fold1
,
1502 __isl_keep isl_qpolynomial_fold
*fold2
)
1507 isl_qpolynomial_list
*list1
, *list2
;
1509 list1
= isl_qpolynomial_fold_peek_list(fold1
);
1510 list2
= isl_qpolynomial_fold_peek_list(fold2
);
1511 n1
= isl_qpolynomial_list_size(list1
);
1512 n2
= isl_qpolynomial_list_size(list2
);
1513 if (!set
|| n1
< 0 || n2
< 0)
1514 return isl_bool_error
;
1516 covers
= fold1
->type
== isl_fold_max
? 1 : -1;
1518 for (i
= 0; i
< n2
; ++i
) {
1519 for (j
= 0; j
< n1
; ++j
) {
1520 isl_qpolynomial
*qp1
, *qp2
, *d
;
1523 qp1
= isl_qpolynomial_list_get_at(list1
, j
);
1524 qp2
= isl_qpolynomial_list_get_at(list2
, i
);
1525 d
= isl_qpolynomial_sub(qp1
, qp2
);
1526 sgn
= isl_qpolynomial_sign(set
, d
);
1527 isl_qpolynomial_free(d
);
1532 return isl_bool_false
;
1535 return isl_bool_true
;
1538 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
1539 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
1542 isl_bool
isl_pw_qpolynomial_fold_covers(
1543 __isl_keep isl_pw_qpolynomial_fold
*pwf1
,
1544 __isl_keep isl_pw_qpolynomial_fold
*pwf2
)
1547 isl_set
*dom1
, *dom2
;
1551 return isl_bool_error
;
1554 return isl_bool_true
;
1556 return isl_bool_false
;
1558 dom1
= isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1
));
1559 dom2
= isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2
));
1560 is_subset
= isl_set_is_subset(dom2
, dom1
);
1564 if (is_subset
< 0 || !is_subset
)
1567 for (i
= 0; i
< pwf2
->n
; ++i
) {
1568 for (j
= 0; j
< pwf1
->n
; ++j
) {
1573 common
= isl_set_intersect(isl_set_copy(pwf1
->p
[j
].set
),
1574 isl_set_copy(pwf2
->p
[i
].set
));
1575 is_empty
= isl_set_is_empty(common
);
1576 if (is_empty
< 0 || is_empty
) {
1577 isl_set_free(common
);
1579 return isl_bool_error
;
1582 covers
= qpolynomial_fold_covers_on_domain(common
,
1583 pwf1
->p
[j
].fold
, pwf2
->p
[i
].fold
);
1584 isl_set_free(common
);
1585 if (covers
< 0 || !covers
)
1590 return isl_bool_true
;
1593 /* isl_qpolynomial_list_map callback that calls
1594 * isl_qpolynomial_morph_domain on "qp".
1596 static __isl_give isl_qpolynomial
*morph_domain(
1597 __isl_take isl_qpolynomial
*qp
, void *user
)
1599 isl_morph
*morph
= user
;
1601 return isl_qpolynomial_morph_domain(qp
, isl_morph_copy(morph
));
1604 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_morph_domain(
1605 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_morph
*morph
)
1608 isl_qpolynomial_list
*list
;
1610 space
= isl_qpolynomial_fold_peek_domain_space(fold
);
1611 if (isl_morph_check_applies(morph
, space
) < 0)
1614 list
= isl_qpolynomial_fold_take_list(fold
);
1615 list
= isl_qpolynomial_list_map(list
, &morph_domain
, morph
);
1616 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1618 space
= isl_morph_get_ran_space(morph
);
1619 isl_space_free(isl_qpolynomial_fold_take_domain_space(fold
));
1620 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1622 isl_morph_free(morph
);
1626 isl_qpolynomial_fold_free(fold
);
1627 isl_morph_free(morph
);
1631 enum isl_fold
isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold
*fold
)
1634 return isl_fold_error
;
1638 /* Return the type of this piecewise quasipolynomial reduction.
1640 enum isl_fold
isl_pw_qpolynomial_fold_get_type(
1641 __isl_keep isl_pw_qpolynomial_fold
*pwf
)
1644 return isl_fold_error
;
1648 enum isl_fold
isl_union_pw_qpolynomial_fold_get_type(
1649 __isl_keep isl_union_pw_qpolynomial_fold
*upwf
)
1652 return isl_fold_error
;
1656 /* isl_qpolynomial_list_map callback that calls
1657 * isl_qpolynomial_lift on "qp".
1659 static __isl_give isl_qpolynomial
*lift(__isl_take isl_qpolynomial
*qp
,
1662 isl_space
*space
= user
;
1664 return isl_qpolynomial_lift(qp
, isl_space_copy(space
));
1667 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_lift(
1668 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_space
*space
)
1670 isl_qpolynomial_list
*list
;
1672 if (!fold
|| !space
)
1675 if (isl_space_is_equal(fold
->dim
, space
)) {
1676 isl_space_free(space
);
1680 list
= isl_qpolynomial_fold_take_list(fold
);
1681 list
= isl_qpolynomial_list_map(list
, &lift
, space
);
1682 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1684 isl_space_free(isl_qpolynomial_fold_take_domain_space(fold
));
1685 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1689 isl_qpolynomial_fold_free(fold
);
1690 isl_space_free(space
);
1694 isl_stat
isl_qpolynomial_fold_foreach_qpolynomial(
1695 __isl_keep isl_qpolynomial_fold
*fold
,
1696 isl_stat (*fn
)(__isl_take isl_qpolynomial
*qp
, void *user
), void *user
)
1698 isl_qpolynomial_list
*list
;
1700 list
= isl_qpolynomial_fold_peek_list(fold
);
1701 return isl_qpolynomial_list_foreach(list
, fn
, user
);
1704 /* Internal data structure for isl_qpolynomial_fold_move_dims
1705 * representing its arguments.
1707 struct isl_fold_move_dims_data
{
1708 enum isl_dim_type dst_type
;
1710 enum isl_dim_type src_type
;
1715 /* isl_qpolynomial_list_map callback for calling
1716 * isl_qpolynomial_move_dims on "qp".
1718 static __isl_give isl_qpolynomial
*move_dims(__isl_take isl_qpolynomial
*qp
,
1721 struct isl_fold_move_dims_data
*data
= user
;
1723 qp
= isl_qpolynomial_move_dims(qp
, data
->dst_type
, data
->dst_pos
,
1724 data
->src_type
, data
->src_pos
, data
->n
);
1728 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_move_dims(
1729 __isl_take isl_qpolynomial_fold
*fold
,
1730 enum isl_dim_type dst_type
, unsigned dst_pos
,
1731 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1733 struct isl_fold_move_dims_data data
=
1734 { dst_type
, dst_pos
, src_type
, src_pos
, n
};
1735 enum isl_dim_type set_src_type
, set_dst_type
;
1737 isl_qpolynomial_list
*list
;
1742 fold
= isl_qpolynomial_fold_cow(fold
);
1746 set_src_type
= domain_type(src_type
);
1747 set_dst_type
= domain_type(dst_type
);
1749 list
= isl_qpolynomial_fold_take_list(fold
);
1750 list
= isl_qpolynomial_list_map(list
, &move_dims
, &data
);
1751 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1753 space
= isl_qpolynomial_fold_take_domain_space(fold
);
1754 space
= isl_space_move_dims(space
, set_dst_type
, dst_pos
,
1755 set_src_type
, src_pos
, n
);
1756 fold
= isl_qpolynomial_fold_restore_domain_space(fold
, space
);
1761 /* Internal data structure for isl_qpolynomial_fold_substitute
1762 * representing its arguments.
1764 struct isl_fold_substitute
{
1765 enum isl_dim_type type
;
1768 isl_qpolynomial
**subs
;
1771 /* isl_qpolynomial_list_map callback for calling
1772 * isl_qpolynomial_substitute on "qp".
1774 static __isl_give isl_qpolynomial
*substitute(__isl_take isl_qpolynomial
*qp
,
1777 struct isl_fold_substitute
*data
= user
;
1779 qp
= isl_qpolynomial_substitute(qp
,
1780 data
->type
, data
->first
, data
->n
, data
->subs
);
1784 /* For each 0 <= i < "n", replace variable "first" + i of type "type"
1785 * in fold->qp[k] by subs[i].
1787 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_substitute(
1788 __isl_take isl_qpolynomial_fold
*fold
,
1789 enum isl_dim_type type
, unsigned first
, unsigned n
,
1790 __isl_keep isl_qpolynomial
**subs
)
1792 struct isl_fold_substitute data
= { type
, first
, n
, subs
};
1793 isl_qpolynomial_list
*list
;
1798 list
= isl_qpolynomial_fold_take_list(fold
);
1799 list
= isl_qpolynomial_list_map(list
, &substitute
, &data
);
1800 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
1805 static isl_stat
add_pwqp(__isl_take isl_pw_qpolynomial
*pwqp
, void *user
)
1807 isl_pw_qpolynomial_fold
*pwf
;
1808 isl_union_pw_qpolynomial_fold
**upwf
;
1809 struct isl_hash_table_entry
*entry
;
1811 upwf
= (isl_union_pw_qpolynomial_fold
**)user
;
1813 entry
= isl_union_pw_qpolynomial_fold_find_part_entry(*upwf
,
1818 pwf
= isl_pw_qpolynomial_fold_from_pw_qpolynomial((*upwf
)->type
, pwqp
);
1822 entry
->data
= isl_pw_qpolynomial_fold_add(entry
->data
, pwf
);
1824 return isl_stat_error
;
1825 if (isl_pw_qpolynomial_fold_is_zero(entry
->data
))
1826 *upwf
= isl_union_pw_qpolynomial_fold_remove_part_entry(
1832 isl_pw_qpolynomial_free(pwqp
);
1833 return isl_stat_error
;
1836 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
1837 __isl_take isl_union_pw_qpolynomial_fold
*upwf
,
1838 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1840 upwf
= isl_union_pw_qpolynomial_fold_align_params(upwf
,
1841 isl_union_pw_qpolynomial_get_space(upwqp
));
1842 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1843 isl_union_pw_qpolynomial_fold_get_space(upwf
));
1845 upwf
= isl_union_pw_qpolynomial_fold_cow(upwf
);
1846 if (!upwf
|| !upwqp
)
1849 if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp
, &add_pwqp
,
1853 isl_union_pw_qpolynomial_free(upwqp
);
1857 isl_union_pw_qpolynomial_fold_free(upwf
);
1858 isl_union_pw_qpolynomial_free(upwqp
);
1862 static isl_bool
join_compatible(__isl_keep isl_space
*space1
,
1863 __isl_keep isl_space
*space2
)
1866 m
= isl_space_has_equal_params(space1
, space2
);
1869 return isl_space_tuple_is_equal(space1
, isl_dim_out
,
1870 space2
, isl_dim_in
);
1873 /* Compute the intersection of the range of the map and the domain
1874 * of the piecewise quasipolynomial reduction and then compute a bound
1875 * on the associated quasipolynomial reduction over all elements
1876 * in this intersection.
1878 * We first introduce some unconstrained dimensions in the
1879 * piecewise quasipolynomial, intersect the resulting domain
1880 * with the wrapped map and the compute the sum.
1882 __isl_give isl_pw_qpolynomial_fold
*isl_map_apply_pw_qpolynomial_fold(
1883 __isl_take isl_map
*map
, __isl_take isl_pw_qpolynomial_fold
*pwf
,
1888 isl_space
*map_space
;
1889 isl_space
*pwf_space
;
1893 ctx
= isl_map_get_ctx(map
);
1897 map_space
= isl_map_get_space(map
);
1898 pwf_space
= isl_pw_qpolynomial_fold_get_space(pwf
);
1899 ok
= join_compatible(map_space
, pwf_space
);
1900 isl_space_free(map_space
);
1901 isl_space_free(pwf_space
);
1905 isl_die(ctx
, isl_error_invalid
, "incompatible dimensions",
1908 n_in
= isl_map_dim(map
, isl_dim_in
);
1911 pwf
= isl_pw_qpolynomial_fold_insert_dims(pwf
, isl_dim_in
, 0, n_in
);
1913 dom
= isl_map_wrap(map
);
1914 pwf
= isl_pw_qpolynomial_fold_reset_domain_space(pwf
,
1915 isl_set_get_space(dom
));
1917 pwf
= isl_pw_qpolynomial_fold_intersect_domain(pwf
, dom
);
1918 pwf
= isl_pw_qpolynomial_fold_bound(pwf
, tight
);
1923 isl_pw_qpolynomial_fold_free(pwf
);
1927 __isl_give isl_pw_qpolynomial_fold
*isl_set_apply_pw_qpolynomial_fold(
1928 __isl_take isl_set
*set
, __isl_take isl_pw_qpolynomial_fold
*pwf
,
1931 return isl_map_apply_pw_qpolynomial_fold(set
, pwf
, tight
);
1934 struct isl_apply_fold_data
{
1935 isl_union_pw_qpolynomial_fold
*upwf
;
1936 isl_union_pw_qpolynomial_fold
*res
;
1941 static isl_stat
pw_qpolynomial_fold_apply(
1942 __isl_take isl_pw_qpolynomial_fold
*pwf
, void *user
)
1946 struct isl_apply_fold_data
*data
= user
;
1949 map_dim
= isl_map_get_space(data
->map
);
1950 pwf_dim
= isl_pw_qpolynomial_fold_get_space(pwf
);
1951 ok
= join_compatible(map_dim
, pwf_dim
);
1952 isl_space_free(map_dim
);
1953 isl_space_free(pwf_dim
);
1956 return isl_stat_error
;
1958 pwf
= isl_map_apply_pw_qpolynomial_fold(isl_map_copy(data
->map
),
1959 pwf
, data
->tight
? &data
->tight
: NULL
);
1960 data
->res
= isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
1963 isl_pw_qpolynomial_fold_free(pwf
);
1968 static isl_stat
map_apply(__isl_take isl_map
*map
, void *user
)
1970 struct isl_apply_fold_data
*data
= user
;
1974 r
= isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
1975 data
->upwf
, &pw_qpolynomial_fold_apply
, data
);
1981 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_map_apply_union_pw_qpolynomial_fold(
1982 __isl_take isl_union_map
*umap
,
1983 __isl_take isl_union_pw_qpolynomial_fold
*upwf
, isl_bool
*tight
)
1987 struct isl_apply_fold_data data
;
1989 upwf
= isl_union_pw_qpolynomial_fold_align_params(upwf
,
1990 isl_union_map_get_space(umap
));
1991 umap
= isl_union_map_align_params(umap
,
1992 isl_union_pw_qpolynomial_fold_get_space(upwf
));
1995 data
.tight
= tight
? isl_bool_true
: isl_bool_false
;
1996 space
= isl_union_pw_qpolynomial_fold_get_space(upwf
);
1997 type
= isl_union_pw_qpolynomial_fold_get_type(upwf
);
1998 data
.res
= isl_union_pw_qpolynomial_fold_zero(space
, type
);
1999 if (isl_union_map_foreach_map(umap
, &map_apply
, &data
) < 0)
2002 isl_union_map_free(umap
);
2003 isl_union_pw_qpolynomial_fold_free(upwf
);
2006 *tight
= data
.tight
;
2010 isl_union_map_free(umap
);
2011 isl_union_pw_qpolynomial_fold_free(upwf
);
2012 isl_union_pw_qpolynomial_fold_free(data
.res
);
2016 __isl_give isl_union_pw_qpolynomial_fold
*isl_union_set_apply_union_pw_qpolynomial_fold(
2017 __isl_take isl_union_set
*uset
,
2018 __isl_take isl_union_pw_qpolynomial_fold
*upwf
, isl_bool
*tight
)
2020 return isl_union_map_apply_union_pw_qpolynomial_fold(uset
, upwf
, tight
);
2023 /* isl_qpolynomial_list_map callback for calling
2024 * isl_qpolynomial_realign_domain on "qp".
2026 static __isl_give isl_qpolynomial
*realign_domain(
2027 __isl_take isl_qpolynomial
*qp
, void *user
)
2029 isl_reordering
*r
= user
;
2031 qp
= isl_qpolynomial_realign_domain(qp
, isl_reordering_copy(r
));
2035 /* Reorder the dimension of "fold" according to the given reordering.
2037 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_realign_domain(
2038 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_reordering
*r
)
2041 isl_qpolynomial_list
*list
;
2043 list
= isl_qpolynomial_fold_take_list(fold
);
2044 list
= isl_qpolynomial_list_map(list
, &realign_domain
, r
);
2045 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2047 space
= isl_reordering_get_space(r
);
2048 fold
= isl_qpolynomial_fold_reset_domain_space(fold
, space
);
2050 isl_reordering_free(r
);
2055 /* isl_qpolynomial_list_map callback for calling
2056 * isl_qpolynomial_mul_isl_int on "qp".
2058 static __isl_give isl_qpolynomial
*mul_int(__isl_take isl_qpolynomial
*qp
,
2063 qp
= isl_qpolynomial_mul_isl_int(qp
, *v
);
2067 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_mul_isl_int(
2068 __isl_take isl_qpolynomial_fold
*fold
, isl_int v
)
2070 isl_qpolynomial_list
*list
;
2072 if (isl_int_is_one(v
))
2074 if (fold
&& isl_int_is_zero(v
)) {
2075 isl_qpolynomial_fold
*zero
;
2076 isl_space
*space
= isl_space_copy(fold
->dim
);
2077 zero
= isl_qpolynomial_fold_empty(fold
->type
, space
);
2078 isl_qpolynomial_fold_free(fold
);
2082 fold
= isl_qpolynomial_fold_cow(fold
);
2086 if (isl_int_is_neg(v
))
2087 fold
->type
= isl_fold_type_negate(fold
->type
);
2089 list
= isl_qpolynomial_fold_take_list(fold
);
2090 list
= isl_qpolynomial_list_map(list
, &mul_int
, &v
);
2091 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2096 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale(
2097 __isl_take isl_qpolynomial_fold
*fold
, isl_int v
)
2099 return isl_qpolynomial_fold_mul_isl_int(fold
, v
);
2102 /* isl_qpolynomial_list_map callback for calling
2103 * isl_qpolynomial_scale_val on "qp".
2105 static __isl_give isl_qpolynomial
*scale_val(__isl_take isl_qpolynomial
*qp
,
2110 qp
= isl_qpolynomial_scale_val(qp
, isl_val_copy(v
));
2114 /* Multiply "fold" by "v".
2116 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale_val(
2117 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_val
*v
)
2119 isl_qpolynomial_list
*list
;
2124 if (isl_val_is_one(v
)) {
2128 if (isl_val_is_zero(v
)) {
2129 isl_qpolynomial_fold
*zero
;
2130 isl_space
*space
= isl_qpolynomial_fold_get_domain_space(fold
);
2131 zero
= isl_qpolynomial_fold_empty(fold
->type
, space
);
2132 isl_qpolynomial_fold_free(fold
);
2136 if (!isl_val_is_rat(v
))
2137 isl_die(isl_qpolynomial_fold_get_ctx(fold
), isl_error_invalid
,
2138 "expecting rational factor", goto error
);
2140 fold
= isl_qpolynomial_fold_cow(fold
);
2144 if (isl_val_is_neg(v
))
2145 fold
->type
= isl_fold_type_negate(fold
->type
);
2147 list
= isl_qpolynomial_fold_take_list(fold
);
2148 list
= isl_qpolynomial_list_map(list
, &scale_val
, v
);
2149 fold
= isl_qpolynomial_fold_restore_list(fold
, list
);
2155 isl_qpolynomial_fold_free(fold
);
2159 /* Divide "fold" by "v".
2161 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_scale_down_val(
2162 __isl_take isl_qpolynomial_fold
*fold
, __isl_take isl_val
*v
)
2167 if (isl_val_is_one(v
)) {
2171 if (!isl_val_is_rat(v
))
2172 isl_die(isl_qpolynomial_fold_get_ctx(fold
), isl_error_invalid
,
2173 "expecting rational factor", goto error
);
2174 if (isl_val_is_zero(v
))
2175 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
2176 "cannot scale down by zero", goto error
);
2178 return isl_qpolynomial_fold_scale_val(fold
, isl_val_inv(v
));
2181 isl_qpolynomial_fold_free(fold
);