2 #include <isl_set_polylib.h>
3 #include <barvinok/options.h>
4 #include <barvinok/util.h>
8 #include "laurent_old.h"
10 #include "section_array.h"
11 #include "remove_equalities.h"
13 extern evalue
*evalue_outer_floor(evalue
*e
);
14 extern int evalue_replace_floor(evalue
*e
, const evalue
*floor
, int var
);
15 extern void evalue_drop_floor(evalue
*e
, const evalue
*floor
);
17 #define ALLOC(type) (type*)malloc(sizeof(type))
18 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
20 /* Apply the variable transformation specified by T and CP on
21 * the polynomial e. T expresses the old variables in terms
22 * of the new variables (and optionally also the new parameters),
23 * while CP expresses the old parameters in terms of the new
26 static void transform_polynomial(evalue
*E
, Matrix
*T
, Matrix
*CP
,
27 unsigned nvar
, unsigned nparam
,
28 unsigned new_nvar
, unsigned new_nparam
)
33 subs
= ALLOCN(evalue
*, nvar
+nparam
);
35 for (j
= 0; j
< nvar
; ++j
) {
37 subs
[j
] = affine2evalue(T
->p
[j
], T
->p
[T
->NbRows
-1][T
->NbColumns
-1],
40 subs
[j
] = evalue_var(j
);
42 for (j
= 0; j
< nparam
; ++j
) {
44 subs
[nvar
+j
] = affine2evalue(CP
->p
[j
], CP
->p
[nparam
][new_nparam
],
47 subs
[nvar
+j
] = evalue_var(j
);
48 evalue_shift_variables(subs
[nvar
+j
], 0, new_nvar
);
51 evalue_substitute(E
, subs
);
54 for (j
= 0; j
< nvar
+nparam
; ++j
)
59 static evalue
*sum_over_polytope_with_equalities(Polyhedron
*P
, evalue
*E
,
61 struct evalue_section_array
*sections
,
62 struct barvinok_options
*options
)
64 unsigned dim
= P
->Dimension
;
65 unsigned new_dim
, new_nparam
;
66 Matrix
*T
= NULL
, *CP
= NULL
;
74 remove_all_equalities(&P
, NULL
, &CP
, &T
, dim
-nvar
, options
->MaxRays
);
81 new_nparam
= CP
? CP
->NbColumns
-1 : dim
- nvar
;
82 new_dim
= T
? T
->NbColumns
-1 : nvar
+ new_nparam
;
84 /* We can avoid these substitutions if E is a constant */
86 transform_polynomial(E
, T
, CP
, nvar
, dim
-nvar
,
87 new_dim
-new_nparam
, new_nparam
);
89 if (new_dim
-new_nparam
> 0) {
90 sum
= barvinok_sum_over_polytope(P
, E
, new_dim
-new_nparam
,
97 sum
->x
.p
= new_enode(partition
, 2, new_dim
);
98 EVALUE_SET_DOMAIN(sum
->x
.p
->arr
[0], P
);
99 value_clear(sum
->x
.p
->arr
[1].d
);
100 sum
->x
.p
->arr
[1] = *E
;
105 evalue_backsubstitute(sum
, CP
, options
->MaxRays
);
115 static evalue
*sum_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
116 struct barvinok_options
*options
)
118 if (options
->summation
== BV_SUM_EULER
)
119 return euler_summate(P
, E
, nvar
, options
);
120 else if (options
->summation
== BV_SUM_LAURENT
)
121 return laurent_summate(P
, E
, nvar
, options
);
122 else if (options
->summation
== BV_SUM_LAURENT_OLD
)
123 return laurent_summate_old(P
, E
, nvar
, options
);
127 /* Count the number of non-zero terms in e when viewed as a polynomial
128 * in only the first nvar variables. "count" is the number counted
131 static int evalue_count_terms(const evalue
*e
, unsigned nvar
, int count
)
135 if (EVALUE_IS_ZERO(*e
))
138 if (value_zero_p(e
->d
))
139 assert(e
->x
.p
->type
== polynomial
);
140 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1)
143 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
144 count
= evalue_count_terms(&e
->x
.p
->arr
[i
], nvar
, count
);
149 /* Create placeholder structure for unzipping.
150 * A "polynomial" is created with size terms in variable pos,
151 * with each term having itself as coefficient.
153 static evalue
*create_placeholder(int size
, int pos
)
156 evalue
*E
= ALLOC(evalue
);
158 E
->x
.p
= new_enode(polynomial
, size
, pos
+1);
159 for (i
= 0; i
< size
; ++i
) {
160 E
->x
.p
->arr
[i
].x
.p
= new_enode(polynomial
, i
+1, pos
+1);
161 for (j
= 0; j
< i
; ++j
)
162 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[j
], 0, 1);
163 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[i
], 1, 1);
168 /* Interchange each non-zero term in e (when viewed as a polynomial
169 * in only the first nvar variables) with a placeholder in ph (created
170 * by create_placeholder), resulting in two polynomials in the
171 * placeholder variable such that for each non-zero term in e
172 * there is a power of the placeholder variable such that the factors
173 * in the first nvar variables form the coefficient of that power in
174 * the first polynomial (e) and the factors in the remaining variables
175 * form the coefficient of that power in the second polynomial (ph).
177 static int evalue_unzip_terms(evalue
*e
, evalue
*ph
, unsigned nvar
, int count
)
181 if (EVALUE_IS_ZERO(*e
))
184 if (value_zero_p(e
->d
))
185 assert(e
->x
.p
->type
== polynomial
);
186 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1) {
188 *e
= ph
->x
.p
->arr
[count
];
189 ph
->x
.p
->arr
[count
] = t
;
193 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
194 count
= evalue_unzip_terms(&e
->x
.p
->arr
[i
], ph
, nvar
, count
);
199 /* Remove n variables at pos (0-based) from the polyhedron P.
200 * Each of these variables is assumed to be completely free,
201 * i.e., there is a line in the polyhedron corresponding to
202 * each of these variables.
204 static Polyhedron
*Polyhedron_Remove_Columns(Polyhedron
*P
, unsigned pos
,
208 unsigned NbConstraints
= 0;
215 assert(pos
<= P
->Dimension
);
217 if (POL_HAS(P
, POL_INEQUALITIES
))
218 NbConstraints
= P
->NbConstraints
;
219 if (POL_HAS(P
, POL_POINTS
))
220 NbRays
= P
->NbRays
- n
;
222 Q
= Polyhedron_Alloc(P
->Dimension
- n
, NbConstraints
, NbRays
);
223 if (POL_HAS(P
, POL_INEQUALITIES
)) {
225 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
226 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
227 Vector_Copy(P
->Constraint
[i
]+1+pos
+n
, Q
->Constraint
[i
]+1+pos
,
231 if (POL_HAS(P
, POL_POINTS
)) {
232 Q
->NbBid
= P
->NbBid
- n
;
233 for (i
= 0; i
< n
; ++i
)
234 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
235 for (i
= 0, j
= 0; i
< P
->NbRays
; ++i
) {
236 int line
= First_Non_Zero(P
->Ray
[i
], 1+P
->Dimension
+1);
238 if (line
-1 >= pos
&& line
-1 < pos
+n
) {
243 assert(i
-j
< Q
->NbRays
);
244 Vector_Copy(P
->Ray
[i
], Q
->Ray
[i
-j
], 1+pos
);
245 Vector_Copy(P
->Ray
[i
]+1+pos
+n
, Q
->Ray
[i
-j
]+1+pos
,
249 POL_SET(Q
, POL_VALID
);
250 if (POL_HAS(P
, POL_INEQUALITIES
))
251 POL_SET(Q
, POL_INEQUALITIES
);
252 if (POL_HAS(P
, POL_POINTS
))
253 POL_SET(Q
, POL_POINTS
);
254 if (POL_HAS(P
, POL_VERTICES
))
255 POL_SET(Q
, POL_VERTICES
);
259 /* Remove n variables at pos (0-based) from the union of polyhedra P.
260 * Each of these variables is assumed to be completely free,
261 * i.e., there is a line in the polyhedron corresponding to
262 * each of these variables.
264 static Polyhedron
*Domain_Remove_Columns(Polyhedron
*P
, unsigned pos
,
268 Polyhedron
**next
= &R
;
270 for (; P
; P
= P
->next
) {
271 *next
= Polyhedron_Remove_Columns(P
, pos
, n
);
272 next
= &(*next
)->next
;
277 /* Drop n parameters starting at first from partition evalue e */
278 static void drop_parameters(evalue
*e
, int first
, int n
)
282 if (EVALUE_IS_ZERO(*e
))
285 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
286 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
287 Polyhedron
*P
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
288 Polyhedron
*Q
= Domain_Remove_Columns(P
, first
, n
);
289 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*i
], Q
);
291 evalue_shift_variables(&e
->x
.p
->arr
[2*i
+1], first
, -n
);
296 static void extract_term_into(const evalue
*src
, int var
, int exp
, evalue
*dst
)
300 if (value_notzero_p(src
->d
) ||
301 src
->x
.p
->type
!= polynomial
||
302 src
->x
.p
->pos
> var
+1) {
304 evalue_copy(dst
, src
);
306 evalue_set_si(dst
, 0, 1);
310 if (src
->x
.p
->pos
== var
+1) {
311 if (src
->x
.p
->size
> exp
)
312 evalue_copy(dst
, &src
->x
.p
->arr
[exp
]);
314 evalue_set_si(dst
, 0, 1);
318 dst
->x
.p
= new_enode(polynomial
, src
->x
.p
->size
, src
->x
.p
->pos
);
319 for (i
= 0; i
< src
->x
.p
->size
; ++i
)
320 extract_term_into(&src
->x
.p
->arr
[i
], var
, exp
,
324 /* Extract the coefficient of var^exp.
326 static evalue
*extract_term(const evalue
*e
, int var
, int exp
)
331 if (EVALUE_IS_ZERO(*e
))
332 return evalue_zero();
334 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
337 res
->x
.p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
338 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
339 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
340 Domain_Copy(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])));
341 extract_term_into(&e
->x
.p
->arr
[2*i
+1], var
, exp
,
342 &res
->x
.p
->arr
[2*i
+1]);
343 reduce_evalue(&res
->x
.p
->arr
[2*i
+1]);
348 /* Insert n free variables at pos (0-based) in the polyhedron P.
350 static Polyhedron
*Polyhedron_Insert_Columns(Polyhedron
*P
, unsigned pos
,
354 unsigned NbConstraints
= 0;
363 assert(pos
<= P
->Dimension
);
365 if (POL_HAS(P
, POL_INEQUALITIES
))
366 NbConstraints
= P
->NbConstraints
;
367 if (POL_HAS(P
, POL_POINTS
))
368 NbRays
= P
->NbRays
+ n
;
370 Q
= Polyhedron_Alloc(P
->Dimension
+n
, NbConstraints
, NbRays
);
371 if (POL_HAS(P
, POL_INEQUALITIES
)) {
373 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
374 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
375 Vector_Copy(P
->Constraint
[i
]+1+pos
, Q
->Constraint
[i
]+1+pos
+n
,
379 if (POL_HAS(P
, POL_POINTS
)) {
380 Q
->NbBid
= P
->NbBid
+ n
;
381 for (i
= 0; i
< n
; ++i
)
382 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
383 for (i
= 0; i
< P
->NbRays
; ++i
) {
384 Vector_Copy(P
->Ray
[i
], Q
->Ray
[n
+i
], 1+pos
);
385 Vector_Copy(P
->Ray
[i
]+1+pos
, Q
->Ray
[n
+i
]+1+pos
+n
,
389 POL_SET(Q
, POL_VALID
);
390 if (POL_HAS(P
, POL_INEQUALITIES
))
391 POL_SET(Q
, POL_INEQUALITIES
);
392 if (POL_HAS(P
, POL_POINTS
))
393 POL_SET(Q
, POL_POINTS
);
394 if (POL_HAS(P
, POL_VERTICES
))
395 POL_SET(Q
, POL_VERTICES
);
399 /* Perform summation of e over a list of 1 or more factors F, with context C.
400 * nvar is the total number of variables in the remaining factors.
401 * extra is the number of placeholder parameters introduced in e,
402 * but not (yet) in F or C.
404 * If there is only one factor left, F is intersected with the
405 * context C, the placeholder variables are added, and then
406 * e is summed over the resulting parametric polytope.
408 * If there is more than one factor left, we create two polynomials
409 * in a new placeholder variable (which is placed after the regular
410 * parameters, but before any previously introduced placeholder
411 * variables) that has the factors of the variables in the first
412 * factor of F and the factor of the remaining variables of
413 * each term as its coefficients.
414 * These two polynomials are then summed over their domains
415 * and afterwards the results are combined and the placeholder
416 * variable is removed again.
418 static evalue
*sum_factors(Polyhedron
*F
, Polyhedron
*C
, evalue
*e
,
419 unsigned nvar
, unsigned extra
,
420 struct barvinok_options
*options
)
423 unsigned nparam
= C
->Dimension
;
424 unsigned F_var
= F
->Dimension
- C
->Dimension
;
430 Polyhedron
*CA
= align_context(C
, nvar
+nparam
, options
->MaxRays
);
431 Polyhedron
*P
= DomainIntersection(F
, CA
, options
->MaxRays
);
432 Polyhedron
*Q
= Polyhedron_Insert_Columns(P
, nvar
+nparam
, extra
);
436 evalue
*sum
= sum_base(Q
, e
, nvar
, options
);
441 n
= evalue_count_terms(e
, F_var
, 0);
442 ph
= create_placeholder(n
, nvar
+nparam
);
443 evalue_shift_variables(e
, nvar
+nparam
, 1);
444 evalue_unzip_terms(e
, ph
, F_var
, 0);
445 evalue_shift_variables(e
, nvar
, -(nvar
-F_var
));
446 evalue_reorder_terms(ph
);
447 evalue_shift_variables(ph
, 0, -F_var
);
449 s2
= sum_factors(F
->next
, C
, ph
, nvar
-F_var
, extra
+1, options
);
452 s1
= sum_factors(F
, C
, e
, F_var
, extra
+1, options
);
455 /* remove placeholder "polynomial" */
459 drop_parameters(s2
, nparam
, 1);
464 for (i
= 0; i
< n
; ++i
) {
466 t1
= extract_term(s1
, nparam
, i
);
467 t2
= extract_term(s2
, nparam
, i
);
476 drop_parameters(s
, nparam
, 1);
480 /* Perform summation over a product of factors F, obtained using
481 * variable transformation T from the original problem specification.
483 * We first perform the corresponding transformation on the polynomial E,
484 * compute the common context over all factors and then perform
485 * the actual summation over the factors.
487 static evalue
*sum_product(Polyhedron
*F
, evalue
*E
, Matrix
*T
, unsigned nparam
,
488 struct barvinok_options
*options
)
492 unsigned nvar
= T
->NbRows
;
496 assert(nvar
== T
->NbColumns
);
497 T2
= Matrix_Alloc(nvar
+1, nvar
+1);
498 for (i
= 0; i
< nvar
; ++i
)
499 Vector_Copy(T
->p
[i
], T2
->p
[i
], nvar
);
500 value_set_si(T2
->p
[nvar
][nvar
], 1);
502 transform_polynomial(E
, T2
, NULL
, nvar
, nparam
, nvar
, nparam
);
504 C
= Factor_Context(F
, nparam
, options
->MaxRays
);
505 if (F
->Dimension
== nparam
) {
511 sum
= sum_factors(F
, C
, E
, nvar
, 0, options
);
519 /* Add two constraints corresponding to floor = floor(e/d),
522 * -e + d t + d-1 >= 0
524 * e is assumed to be an affine expression.
526 Polyhedron
*add_floor_var(Polyhedron
*P
, unsigned nvar
, const evalue
*floor
,
527 struct barvinok_options
*options
)
530 unsigned dim
= P
->Dimension
+1;
531 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
+2, 2+dim
);
533 Value
*d
= &M
->p
[0][1+nvar
];
534 evalue_extract_affine(floor
, M
->p
[0]+1, M
->p
[0]+1+dim
, d
);
535 value_oppose(*d
, *d
);
536 value_set_si(M
->p
[0][0], 1);
537 value_set_si(M
->p
[1][0], 1);
538 Vector_Oppose(M
->p
[0]+1, M
->p
[1]+1, M
->NbColumns
-1);
539 value_subtract(M
->p
[1][1+dim
], M
->p
[1][1+dim
], *d
);
540 value_decrement(M
->p
[1][1+dim
], M
->p
[1][1+dim
]);
542 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
543 Vector_Copy(P
->Constraint
[i
], M
->p
[i
+2], 1+nvar
);
544 Vector_Copy(P
->Constraint
[i
]+1+nvar
, M
->p
[i
+2]+1+nvar
+1, dim
-nvar
-1+1);
547 CP
= Constraints2Polyhedron(M
, options
->MaxRays
);
552 static evalue
*evalue_add(evalue
*a
, evalue
*b
)
563 /* Compute sum of a step-polynomial over a polytope by grouping
564 * terms containing the same floor-expressions and introducing
565 * new variables for each such expression.
566 * In particular, while there is any floor-expression left,
567 * the step-polynomial is split into a polynomial containing
568 * the expression, which is then converted to a new variable,
569 * and a polynomial not containing the expression.
571 static evalue
*sum_step_polynomial(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
572 struct barvinok_options
*options
)
579 while ((floor
= evalue_outer_floor(cur
))) {
582 evalue
*converted_floor
;
584 /* Ignore floors that do not depend on variables. */
585 if (value_notzero_p(floor
->d
) || floor
->x
.p
->pos
>= nvar
+1)
588 converted
= evalue_dup(cur
);
589 converted_floor
= evalue_dup(floor
);
590 evalue_shift_variables(converted
, nvar
, 1);
591 evalue_shift_variables(converted_floor
, nvar
, 1);
592 evalue_replace_floor(converted
, converted_floor
, nvar
);
593 CP
= add_floor_var(P
, nvar
, converted_floor
, options
);
594 evalue_free(converted_floor
);
595 t
= sum_step_polynomial(CP
, converted
, nvar
+1, options
);
596 evalue_free(converted
);
598 sum
= evalue_add(t
, sum
);
601 cur
= evalue_dup(cur
);
602 evalue_drop_floor(cur
, floor
);
606 evalue_floor2frac(cur
);
610 if (EVALUE_IS_ZERO(*cur
))
614 unsigned nparam
= P
->Dimension
- nvar
;
615 Polyhedron
*F
= Polyhedron_Factor(P
, nparam
, &T
, options
->MaxRays
);
617 t
= sum_base(P
, cur
, nvar
, options
);
620 cur
= evalue_dup(cur
);
621 t
= sum_product(F
, cur
, T
, nparam
, options
);
628 return evalue_add(t
, sum
);
631 evalue
*barvinok_sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
632 struct evalue_section_array
*sections
,
633 struct barvinok_options
*options
)
636 return sum_over_polytope_with_equalities(P
, E
, nvar
, sections
, options
);
638 if (options
->summation
== BV_SUM_BERNOULLI
)
639 return bernoulli_summate(P
, E
, nvar
, sections
, options
);
640 else if (options
->summation
== BV_SUM_BOX
)
641 return box_summate(P
, E
, nvar
, options
->MaxRays
);
643 evalue_frac2floor2(E
, 0);
645 return sum_step_polynomial(P
, E
, nvar
, options
);
648 evalue
*barvinok_summate(evalue
*e
, int nvar
, struct barvinok_options
*options
)
651 struct evalue_section_array sections
;
655 if (nvar
== 0 || EVALUE_IS_ZERO(*e
))
656 return evalue_dup(e
);
658 assert(value_zero_p(e
->d
));
659 assert(e
->x
.p
->type
== partition
);
661 evalue_section_array_init(§ions
);
664 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
666 for (D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]); D
; D
= D
->next
) {
667 Polyhedron
*next
= D
->next
;
671 tmp
= barvinok_sum_over_polytope(D
, &e
->x
.p
->arr
[2*i
+1], nvar
,
687 static __isl_give isl_pw_qpolynomial
*add_unbounded_guarded_qp(
688 __isl_take isl_pw_qpolynomial
*sum
,
689 __isl_take isl_basic_set
*bset
, __isl_take isl_qpolynomial
*qp
)
693 if (!sum
|| !bset
|| !qp
)
696 zero
= isl_qpolynomial_is_zero(qp
);
703 isl_pw_qpolynomial
*pwqp
;
705 dim
= isl_pw_qpolynomial_get_dim(sum
);
706 set
= isl_set_from_basic_set(isl_basic_set_copy(bset
));
707 set
= isl_map_domain(isl_map_from_range(set
));
708 set
= isl_set_reset_dim(set
, isl_dim_copy(dim
));
709 pwqp
= isl_pw_qpolynomial_alloc(set
, isl_qpolynomial_nan(dim
));
710 sum
= isl_pw_qpolynomial_add(sum
, pwqp
);
713 isl_basic_set_free(bset
);
714 isl_qpolynomial_free(qp
);
717 isl_basic_set_free(bset
);
718 isl_qpolynomial_free(qp
);
719 isl_pw_qpolynomial_free(sum
);
723 struct barvinok_summate_data
{
725 __isl_take isl_qpolynomial
*qp
;
726 isl_pw_qpolynomial
*sum
;
730 struct evalue_section_array sections
;
731 struct barvinok_options
*options
;
734 static int add_basic_guarded_qp(__isl_take isl_basic_set
*bset
, void *user
)
736 struct barvinok_summate_data
*data
= user
;
739 isl_pw_qpolynomial
*pwqp
;
741 unsigned nparam
= isl_basic_set_dim(bset
, isl_dim_param
);
742 unsigned nvar
= isl_basic_set_dim(bset
, isl_dim_set
);
748 bounded
= isl_basic_set_is_bounded(bset
);
753 data
->sum
= add_unbounded_guarded_qp(data
->sum
, bset
,
754 isl_qpolynomial_copy(data
->qp
));
758 dim
= isl_basic_set_get_dim(bset
);
759 dim
= isl_dim_domain(isl_dim_from_range(dim
));
761 P
= isl_basic_set_to_polylib(bset
);
762 tmp
= barvinok_sum_over_polytope(P
, data
->e
, nvar
,
763 &data
->sections
, data
->options
);
766 pwqp
= isl_pw_qpolynomial_from_evalue(dim
, tmp
);
768 pwqp
= isl_pw_qpolynomial_reset_dim(pwqp
, isl_dim_copy(data
->dim
));
769 data
->sum
= isl_pw_qpolynomial_add(data
->sum
, pwqp
);
771 isl_basic_set_free(bset
);
775 isl_basic_set_free(bset
);
779 static int add_guarded_qp(__isl_take isl_set
*set
, __isl_take isl_qpolynomial
*qp
,
783 struct barvinok_summate_data
*data
= user
;
790 if (data
->wrapping
) {
791 unsigned nparam
= isl_set_dim(set
, isl_dim_param
);
792 isl_qpolynomial
*qp2
= isl_qpolynomial_copy(qp
);
793 set
= isl_set_move_dims(set
, isl_dim_param
, nparam
,
794 isl_dim_set
, 0, data
->n_in
);
795 qp2
= isl_qpolynomial_move_dims(qp2
, isl_dim_param
, nparam
,
796 isl_dim_set
, 0, data
->n_in
);
797 data
->e
= isl_qpolynomial_to_evalue(qp2
);
798 isl_qpolynomial_free(qp2
);
800 data
->e
= isl_qpolynomial_to_evalue(qp
);
804 evalue_section_array_init(&data
->sections
);
806 set
= isl_set_make_disjoint(set
);
807 set
= isl_set_compute_divs(set
);
809 r
= isl_set_foreach_basic_set(set
, &add_basic_guarded_qp
, data
);
811 free(data
->sections
.s
);
813 evalue_free(data
->e
);
816 isl_qpolynomial_free(qp
);
821 isl_qpolynomial_free(qp
);
825 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_sum(
826 __isl_take isl_pw_qpolynomial
*pwqp
)
829 struct barvinok_summate_data data
;
830 int options_allocated
= 0;
839 nvar
= isl_pw_qpolynomial_dim(pwqp
, isl_dim_set
);
841 return isl_pw_qpolynomial_drop_dims(pwqp
, isl_dim_set
, 0, 0);
843 data
.dim
= isl_pw_qpolynomial_get_dim(pwqp
);
844 data
.wrapping
= isl_dim_is_wrapping(data
.dim
);
846 data
.dim
= isl_dim_unwrap(data
.dim
);
847 data
.n_in
= isl_dim_size(data
.dim
, isl_dim_in
);
848 nvar
= isl_dim_size(data
.dim
, isl_dim_out
);
849 data
.dim
= isl_dim_domain(data
.dim
);
851 return isl_pw_qpolynomial_reset_dim(pwqp
, data
.dim
);
854 data
.dim
= isl_dim_drop(data
.dim
, isl_dim_set
, 0, nvar
);
857 data
.sum
= isl_pw_qpolynomial_zero(isl_dim_copy(data
.dim
));
859 ctx
= isl_pw_qpolynomial_get_ctx(pwqp
);
860 data
.options
= isl_ctx_peek_barvinok_options(ctx
);
862 data
.options
= barvinok_options_new_with_defaults();
863 options_allocated
= 1;
866 if (isl_pw_qpolynomial_foreach_lifted_piece(pwqp
,
867 add_guarded_qp
, &data
) < 0)
870 if (options_allocated
)
871 barvinok_options_free(data
.options
);
873 isl_dim_free(data
.dim
);
875 isl_pw_qpolynomial_free(pwqp
);
879 if (options_allocated
)
880 barvinok_options_free(data
.options
);
881 isl_pw_qpolynomial_free(pwqp
);
882 isl_dim_free(data
.dim
);
883 isl_pw_qpolynomial_free(data
.sum
);
887 static int pw_qpolynomial_sum(__isl_take isl_pw_qpolynomial
*pwqp
, void *user
)
889 isl_union_pw_qpolynomial
**res
= (isl_union_pw_qpolynomial
**)user
;
890 isl_pw_qpolynomial
*sum
;
892 sum
= isl_pw_qpolynomial_sum(pwqp
);
893 *res
= isl_union_pw_qpolynomial_add_pw_qpolynomial(*res
, sum
);
898 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_sum(
899 __isl_take isl_union_pw_qpolynomial
*upwqp
)
902 isl_union_pw_qpolynomial
*res
;
904 dim
= isl_union_pw_qpolynomial_get_dim(upwqp
);
905 res
= isl_union_pw_qpolynomial_zero(dim
);
906 if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp
,
907 &pw_qpolynomial_sum
, &res
) < 0)
909 isl_union_pw_qpolynomial_free(upwqp
);
913 isl_union_pw_qpolynomial_free(upwqp
);
914 isl_union_pw_qpolynomial_free(res
);
918 static int compatible_range(__isl_keep isl_dim
*dim1
, __isl_keep isl_dim
*dim2
)
921 m
= isl_dim_match(dim1
, isl_dim_param
, dim2
, isl_dim_param
);
924 return isl_dim_tuple_match(dim1
, isl_dim_out
, dim2
, isl_dim_set
);
927 /* Compute the intersection of the range of the map and the domain
928 * of the piecewise quasipolynomial and then sum the associated
929 * quasipolynomial over all elements in this intersection.
931 * We first introduce some unconstrained dimensions in the
932 * piecewise quasipolynomial, intersect the resulting domain
933 * with the wrapped map and then compute the sum.
935 __isl_give isl_pw_qpolynomial
*isl_map_apply_pw_qpolynomial(
936 __isl_take isl_map
*map
, __isl_take isl_pw_qpolynomial
*pwqp
)
945 ctx
= isl_map_get_ctx(map
);
949 map_dim
= isl_map_get_dim(map
);
950 pwqp_dim
= isl_pw_qpolynomial_get_dim(pwqp
);
951 ok
= compatible_range(map_dim
, pwqp_dim
);
952 isl_dim_free(map_dim
);
953 isl_dim_free(pwqp_dim
);
955 isl_die(ctx
, isl_error_invalid
, "incompatible dimensions",
958 n_in
= isl_map_dim(map
, isl_dim_in
);
959 pwqp
= isl_pw_qpolynomial_insert_dims(pwqp
, isl_dim_set
, 0, n_in
);
961 dom
= isl_map_wrap(map
);
962 pwqp
= isl_pw_qpolynomial_reset_dim(pwqp
, isl_set_get_dim(dom
));
964 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, dom
);
965 pwqp
= isl_pw_qpolynomial_sum(pwqp
);
970 isl_pw_qpolynomial_free(pwqp
);
974 __isl_give isl_pw_qpolynomial
*isl_set_apply_pw_qpolynomial(
975 __isl_take isl_set
*set
, __isl_take isl_pw_qpolynomial
*pwqp
)
979 map
= isl_map_from_range(set
);
980 return isl_map_apply_pw_qpolynomial(map
, pwqp
);
983 struct barvinok_apply_data
{
984 isl_union_pw_qpolynomial
*upwqp
;
985 isl_union_pw_qpolynomial
*res
;
989 static int pw_qpolynomial_apply(__isl_take isl_pw_qpolynomial
*pwqp
, void *user
)
993 struct barvinok_apply_data
*data
= user
;
996 map_dim
= isl_map_get_dim(data
->map
);
997 pwqp_dim
= isl_pw_qpolynomial_get_dim(pwqp
);
998 ok
= compatible_range(map_dim
, pwqp_dim
);
999 isl_dim_free(map_dim
);
1000 isl_dim_free(pwqp_dim
);
1003 pwqp
= isl_map_apply_pw_qpolynomial(isl_map_copy(data
->map
),
1005 data
->res
= isl_union_pw_qpolynomial_add_pw_qpolynomial(
1008 isl_pw_qpolynomial_free(pwqp
);
1013 static int map_apply(__isl_take isl_map
*map
, void *user
)
1015 struct barvinok_apply_data
*data
= user
;
1019 r
= isl_union_pw_qpolynomial_foreach_pw_qpolynomial(data
->upwqp
,
1020 &pw_qpolynomial_apply
, data
);
1026 __isl_give isl_union_pw_qpolynomial
*isl_union_map_apply_union_pw_qpolynomial(
1027 __isl_take isl_union_map
*umap
,
1028 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1031 struct barvinok_apply_data data
;
1033 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1034 isl_union_map_get_dim(umap
));
1035 umap
= isl_union_map_align_params(umap
,
1036 isl_union_pw_qpolynomial_get_dim(upwqp
));
1039 dim
= isl_union_pw_qpolynomial_get_dim(upwqp
);
1040 data
.res
= isl_union_pw_qpolynomial_zero(dim
);
1041 if (isl_union_map_foreach_map(umap
, &map_apply
, &data
) < 0)
1044 isl_union_map_free(umap
);
1045 isl_union_pw_qpolynomial_free(upwqp
);
1049 isl_union_map_free(umap
);
1050 isl_union_pw_qpolynomial_free(upwqp
);
1051 isl_union_pw_qpolynomial_free(data
.res
);
1055 __isl_give isl_union_pw_qpolynomial
*isl_union_set_apply_union_pw_qpolynomial(
1056 __isl_take isl_union_set
*uset
,
1057 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1059 isl_union_map
*umap
;
1061 umap
= isl_union_map_from_range(uset
);
1062 return isl_union_map_apply_union_pw_qpolynomial(umap
, upwqp
);
1065 evalue
*evalue_sum(evalue
*E
, int nvar
, unsigned MaxRays
)
1068 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1069 options
->MaxRays
= MaxRays
;
1070 sum
= barvinok_summate(E
, nvar
, options
);
1071 barvinok_options_free(options
);
1075 evalue
*esum(evalue
*e
, int nvar
)
1078 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1079 sum
= barvinok_summate(e
, nvar
, options
);
1080 barvinok_options_free(options
);
1084 /* Turn unweighted counting problem into "weighted" counting problem
1085 * with weight equal to 1 and call barvinok_summate on this weighted problem.
1087 evalue
*barvinok_summate_unweighted(Polyhedron
*P
, Polyhedron
*C
,
1088 struct barvinok_options
*options
)
1094 if (emptyQ(P
) || emptyQ(C
))
1095 return evalue_zero();
1097 CA
= align_context(C
, P
->Dimension
, options
->MaxRays
);
1098 D
= DomainIntersection(P
, CA
, options
->MaxRays
);
1103 return evalue_zero();
1107 e
.x
.p
= new_enode(partition
, 2, P
->Dimension
);
1108 EVALUE_SET_DOMAIN(e
.x
.p
->arr
[0], D
);
1109 evalue_set_si(&e
.x
.p
->arr
[1], 1, 1);
1110 sum
= barvinok_summate(&e
, P
->Dimension
- C
->Dimension
, options
);
1111 free_evalue_refs(&e
);