4 #include <isl/union_set.h>
5 #include <isl/union_map.h>
6 #include <isl/polynomial.h>
7 #include <isl_set_polylib.h>
8 #include <barvinok/isl.h>
9 #include <barvinok/polylib.h>
10 #include <barvinok/options.h>
11 #include <barvinok/util.h>
12 #include "bernoulli.h"
15 #include "laurent_old.h"
16 #include "param_util.h"
17 #include "reduce_domain.h"
19 #include "section_array.h"
20 #include "remove_equalities.h"
22 extern evalue
*evalue_outer_floor(evalue
*e
);
23 extern int evalue_replace_floor(evalue
*e
, const evalue
*floor
, int var
);
24 extern void evalue_drop_floor(evalue
*e
, const evalue
*floor
);
26 #define ALLOC(type) (type*)malloc(sizeof(type))
27 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
29 /* Apply the variable transformation specified by T and CP on
30 * the polynomial e. T expresses the old variables in terms
31 * of the new variables (and optionally also the new parameters),
32 * while CP expresses the old parameters in terms of the new
35 static void transform_polynomial(evalue
*E
, Matrix
*T
, Matrix
*CP
,
36 unsigned nvar
, unsigned nparam
,
37 unsigned new_nvar
, unsigned new_nparam
)
42 subs
= ALLOCN(evalue
*, nvar
+nparam
);
44 for (j
= 0; j
< nvar
; ++j
) {
46 subs
[j
] = affine2evalue(T
->p
[j
], T
->p
[T
->NbRows
-1][T
->NbColumns
-1],
49 subs
[j
] = evalue_var(j
);
51 for (j
= 0; j
< nparam
; ++j
) {
53 subs
[nvar
+j
] = affine2evalue(CP
->p
[j
], CP
->p
[nparam
][new_nparam
],
56 subs
[nvar
+j
] = evalue_var(j
);
57 evalue_shift_variables(subs
[nvar
+j
], 0, new_nvar
);
60 evalue_substitute(E
, subs
);
63 for (j
= 0; j
< nvar
+nparam
; ++j
)
68 /* Compute the sum of the quasi-polynomial E
69 * over a 0D (non-empty, but possibly parametric) polytope P.
73 * We simply return a partition evalue with P as domain and E as value.
75 static evalue
*sum_over_polytope_0D(Polyhedron
*P
, evalue
*E
)
81 sum
->x
.p
= new_enode(partition
, 2, P
->Dimension
);
82 EVALUE_SET_DOMAIN(sum
->x
.p
->arr
[0], P
);
83 value_clear(sum
->x
.p
->arr
[1].d
);
84 sum
->x
.p
->arr
[1] = *E
;
90 static evalue
*sum_with_equalities(Polyhedron
*P
, evalue
*E
,
91 unsigned nvar
, struct evalue_section_array
*sections
,
92 struct barvinok_options
*options
,
93 evalue
*(*base
)(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
94 struct evalue_section_array
*sections
,
95 struct barvinok_options
*options
))
97 unsigned dim
= P
->Dimension
;
98 unsigned new_dim
, new_nparam
;
99 Matrix
*T
= NULL
, *CP
= NULL
;
103 return evalue_zero();
107 remove_all_equalities(&P
, NULL
, &CP
, &T
, dim
-nvar
, options
->MaxRays
);
111 return evalue_zero();
114 new_nparam
= CP
? CP
->NbColumns
-1 : dim
- nvar
;
115 new_dim
= T
? T
->NbColumns
-1 : nvar
+ new_nparam
;
117 /* We can avoid these substitutions if E is a constant */
119 transform_polynomial(E
, T
, CP
, nvar
, dim
-nvar
,
120 new_dim
-new_nparam
, new_nparam
);
122 if (new_dim
-new_nparam
> 0) {
123 sum
= base(P
, E
, new_dim
-new_nparam
, sections
, options
);
127 sum
= sum_over_polytope_0D(P
, E
);
131 evalue_backsubstitute(sum
, CP
, options
->MaxRays
);
141 static evalue
*sum_over_polytope_with_equalities(Polyhedron
*P
, evalue
*E
,
142 unsigned nvar
, struct evalue_section_array
*sections
,
143 struct barvinok_options
*options
)
145 return sum_with_equalities(P
, E
, nvar
, sections
, options
,
146 &barvinok_sum_over_polytope
);
149 static evalue
*sum_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
150 struct barvinok_options
*options
);
152 static evalue
*sum_base_wrap(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
153 struct evalue_section_array
*sections
, struct barvinok_options
*options
)
155 return sum_base(P
, E
, nvar
, options
);
158 static evalue
*sum_base_with_equalities(Polyhedron
*P
, evalue
*E
,
159 unsigned nvar
, struct barvinok_options
*options
)
161 return sum_with_equalities(P
, E
, nvar
, NULL
, options
, &sum_base_wrap
);
164 /* The substitutions in sum_step_polynomial may have reintroduced equalities
165 * (in particular, one of the floor expressions may be equal to one of
166 * the variables), so we need to check for them again.
167 * Similarly, the construction of the Param_Polyhedron may involve
168 * some simplification that exposes one or more equality constraints.
170 static evalue
*sum_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
171 struct barvinok_options
*options
)
174 Param_Polyhedron
*PP
;
178 return sum_base_with_equalities(P
, E
, nvar
, options
);
180 U
= Universe_Polyhedron(P
->Dimension
- nvar
);
181 PP
= Polyhedron2Param_Polyhedron(P
, U
, options
);
182 if (Param_Polyhedron_Is_Lower_Dimensional(PP
)) {
183 P
= Param_Polyhedron2Polyhedron(PP
, options
);
185 Param_Polyhedron_Free(PP
);
186 sum
= sum_base_with_equalities(P
, E
, nvar
, options
);
190 TC
= true_context(P
, U
, options
->MaxRays
);
192 if (options
->summation
== BV_SUM_EULER
)
193 sum
= euler_summate(PP
, TC
, E
, nvar
, options
);
194 else if (options
->summation
== BV_SUM_LAURENT
)
195 sum
= laurent_summate(PP
, TC
, E
, nvar
, options
);
196 else if (options
->summation
== BV_SUM_LAURENT_OLD
)
197 sum
= laurent_summate_old(PP
, TC
, E
, nvar
, options
);
203 Param_Polyhedron_Free(PP
);
208 /* Count the number of non-zero terms in e when viewed as a polynomial
209 * in only the first nvar variables. "count" is the number counted
212 static int evalue_count_terms(const evalue
*e
, unsigned nvar
, int count
)
216 if (EVALUE_IS_ZERO(*e
))
219 if (value_zero_p(e
->d
))
220 assert(e
->x
.p
->type
== polynomial
);
221 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1)
224 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
225 count
= evalue_count_terms(&e
->x
.p
->arr
[i
], nvar
, count
);
230 /* Create placeholder structure for unzipping.
231 * A "polynomial" is created with size terms in variable pos,
232 * with each term having itself as coefficient.
234 static evalue
*create_placeholder(int size
, int pos
)
237 evalue
*E
= ALLOC(evalue
);
239 E
->x
.p
= new_enode(polynomial
, size
, pos
+1);
240 for (i
= 0; i
< size
; ++i
) {
241 E
->x
.p
->arr
[i
].x
.p
= new_enode(polynomial
, i
+1, pos
+1);
242 for (j
= 0; j
< i
; ++j
)
243 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[j
], 0, 1);
244 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[i
], 1, 1);
249 /* Interchange each non-zero term in e (when viewed as a polynomial
250 * in only the first nvar variables) with a placeholder in ph (created
251 * by create_placeholder), resulting in two polynomials in the
252 * placeholder variable such that for each non-zero term in e
253 * there is a power of the placeholder variable such that the factors
254 * in the first nvar variables form the coefficient of that power in
255 * the first polynomial (e) and the factors in the remaining variables
256 * form the coefficient of that power in the second polynomial (ph).
258 static int evalue_unzip_terms(evalue
*e
, evalue
*ph
, unsigned nvar
, int count
)
262 if (EVALUE_IS_ZERO(*e
))
265 if (value_zero_p(e
->d
))
266 assert(e
->x
.p
->type
== polynomial
);
267 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1) {
269 *e
= ph
->x
.p
->arr
[count
];
270 ph
->x
.p
->arr
[count
] = t
;
274 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
275 count
= evalue_unzip_terms(&e
->x
.p
->arr
[i
], ph
, nvar
, count
);
280 /* Remove n variables at pos (0-based) from the polyhedron P.
281 * Each of these variables is assumed to be completely free,
282 * i.e., there is a line in the polyhedron corresponding to
283 * each of these variables.
285 static Polyhedron
*Polyhedron_Remove_Columns(Polyhedron
*P
, unsigned pos
,
289 unsigned NbConstraints
= 0;
296 assert(pos
<= P
->Dimension
);
298 if (POL_HAS(P
, POL_INEQUALITIES
))
299 NbConstraints
= P
->NbConstraints
;
300 if (POL_HAS(P
, POL_POINTS
))
301 NbRays
= P
->NbRays
- n
;
303 Q
= Polyhedron_Alloc(P
->Dimension
- n
, NbConstraints
, NbRays
);
304 if (POL_HAS(P
, POL_INEQUALITIES
)) {
306 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
307 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
308 Vector_Copy(P
->Constraint
[i
]+1+pos
+n
, Q
->Constraint
[i
]+1+pos
,
312 if (POL_HAS(P
, POL_POINTS
)) {
313 Q
->NbBid
= P
->NbBid
- n
;
314 for (i
= 0; i
< n
; ++i
)
315 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
316 for (i
= 0, j
= 0; i
< P
->NbRays
; ++i
) {
317 int line
= First_Non_Zero(P
->Ray
[i
], 1+P
->Dimension
+1);
319 if (line
-1 >= pos
&& line
-1 < pos
+n
) {
324 assert(i
-j
< Q
->NbRays
);
325 Vector_Copy(P
->Ray
[i
], Q
->Ray
[i
-j
], 1+pos
);
326 Vector_Copy(P
->Ray
[i
]+1+pos
+n
, Q
->Ray
[i
-j
]+1+pos
,
330 POL_SET(Q
, POL_VALID
);
331 if (POL_HAS(P
, POL_INEQUALITIES
))
332 POL_SET(Q
, POL_INEQUALITIES
);
333 if (POL_HAS(P
, POL_POINTS
))
334 POL_SET(Q
, POL_POINTS
);
335 if (POL_HAS(P
, POL_VERTICES
))
336 POL_SET(Q
, POL_VERTICES
);
340 /* Remove n variables at pos (0-based) from the union of polyhedra P.
341 * Each of these variables is assumed to be completely free,
342 * i.e., there is a line in the polyhedron corresponding to
343 * each of these variables.
345 static Polyhedron
*Domain_Remove_Columns(Polyhedron
*P
, unsigned pos
,
349 Polyhedron
**next
= &R
;
351 for (; P
; P
= P
->next
) {
352 *next
= Polyhedron_Remove_Columns(P
, pos
, n
);
353 next
= &(*next
)->next
;
358 /* Drop n parameters starting at first from partition evalue e */
359 static void drop_parameters(evalue
*e
, int first
, int n
)
363 if (EVALUE_IS_ZERO(*e
))
366 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
367 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
368 Polyhedron
*P
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
369 Polyhedron
*Q
= Domain_Remove_Columns(P
, first
, n
);
370 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*i
], Q
);
372 evalue_shift_variables(&e
->x
.p
->arr
[2*i
+1], first
, -n
);
377 static void extract_term_into(const evalue
*src
, int var
, int exp
, evalue
*dst
)
381 if (value_notzero_p(src
->d
) ||
382 src
->x
.p
->type
!= polynomial
||
383 src
->x
.p
->pos
> var
+1) {
385 evalue_copy(dst
, src
);
387 evalue_set_si(dst
, 0, 1);
391 if (src
->x
.p
->pos
== var
+1) {
392 if (src
->x
.p
->size
> exp
)
393 evalue_copy(dst
, &src
->x
.p
->arr
[exp
]);
395 evalue_set_si(dst
, 0, 1);
399 dst
->x
.p
= new_enode(polynomial
, src
->x
.p
->size
, src
->x
.p
->pos
);
400 for (i
= 0; i
< src
->x
.p
->size
; ++i
)
401 extract_term_into(&src
->x
.p
->arr
[i
], var
, exp
,
405 /* Extract the coefficient of var^exp.
407 static evalue
*extract_term(const evalue
*e
, int var
, int exp
)
412 if (EVALUE_IS_ZERO(*e
))
413 return evalue_zero();
415 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
418 res
->x
.p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
419 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
420 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
421 Domain_Copy(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])));
422 extract_term_into(&e
->x
.p
->arr
[2*i
+1], var
, exp
,
423 &res
->x
.p
->arr
[2*i
+1]);
424 reduce_evalue(&res
->x
.p
->arr
[2*i
+1]);
429 /* Insert n free variables at pos (0-based) in the polyhedron P.
431 static Polyhedron
*Polyhedron_Insert_Columns(Polyhedron
*P
, unsigned pos
,
435 unsigned NbConstraints
= 0;
444 assert(pos
<= P
->Dimension
);
446 if (POL_HAS(P
, POL_INEQUALITIES
))
447 NbConstraints
= P
->NbConstraints
;
448 if (POL_HAS(P
, POL_POINTS
))
449 NbRays
= P
->NbRays
+ n
;
451 Q
= Polyhedron_Alloc(P
->Dimension
+n
, NbConstraints
, NbRays
);
452 if (POL_HAS(P
, POL_INEQUALITIES
)) {
454 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
455 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
456 Vector_Copy(P
->Constraint
[i
]+1+pos
, Q
->Constraint
[i
]+1+pos
+n
,
460 if (POL_HAS(P
, POL_POINTS
)) {
461 Q
->NbBid
= P
->NbBid
+ n
;
462 for (i
= 0; i
< n
; ++i
)
463 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
464 for (i
= 0; i
< P
->NbRays
; ++i
) {
465 Vector_Copy(P
->Ray
[i
], Q
->Ray
[n
+i
], 1+pos
);
466 Vector_Copy(P
->Ray
[i
]+1+pos
, Q
->Ray
[n
+i
]+1+pos
+n
,
470 POL_SET(Q
, POL_VALID
);
471 if (POL_HAS(P
, POL_INEQUALITIES
))
472 POL_SET(Q
, POL_INEQUALITIES
);
473 if (POL_HAS(P
, POL_POINTS
))
474 POL_SET(Q
, POL_POINTS
);
475 if (POL_HAS(P
, POL_VERTICES
))
476 POL_SET(Q
, POL_VERTICES
);
480 /* Perform summation of e over a list of 1 or more factors F, with context C.
481 * nvar is the total number of variables in the remaining factors.
482 * extra is the number of placeholder parameters introduced in e,
483 * but not (yet) in F or C.
485 * If there is only one factor left, F is intersected with the
486 * context C, the placeholder variables are added, and then
487 * e is summed over the resulting parametric polytope.
489 * If there is more than one factor left, we create two polynomials
490 * in a new placeholder variable (which is placed after the regular
491 * parameters, but before any previously introduced placeholder
492 * variables) that has the factors of the variables in the first
493 * factor of F and the factor of the remaining variables of
494 * each term as its coefficients.
495 * These two polynomials are then summed over their domains
496 * and afterwards the results are combined and the placeholder
497 * variable is removed again.
499 static evalue
*sum_factors(Polyhedron
*F
, Polyhedron
*C
, evalue
*e
,
500 unsigned nvar
, unsigned extra
,
501 struct barvinok_options
*options
)
503 unsigned nparam
= C
->Dimension
;
504 unsigned F_var
= F
->Dimension
- C
->Dimension
;
510 Polyhedron
*CA
= align_context(C
, nvar
+nparam
, options
->MaxRays
);
511 Polyhedron
*P
= DomainIntersection(F
, CA
, options
->MaxRays
);
512 Polyhedron
*Q
= Polyhedron_Insert_Columns(P
, nvar
+nparam
, extra
);
516 evalue
*sum
= sum_base(Q
, e
, nvar
, options
);
521 n
= evalue_count_terms(e
, F_var
, 0);
522 ph
= create_placeholder(n
, nvar
+nparam
);
523 evalue_shift_variables(e
, nvar
+nparam
, 1);
524 evalue_unzip_terms(e
, ph
, F_var
, 0);
525 evalue_shift_variables(e
, nvar
, -(nvar
-F_var
));
526 evalue_reorder_terms(ph
);
527 evalue_shift_variables(ph
, 0, -F_var
);
529 s2
= sum_factors(F
->next
, C
, ph
, nvar
-F_var
, extra
+1, options
);
532 s1
= sum_factors(F
, C
, e
, F_var
, extra
+1, options
);
535 /* remove placeholder "polynomial" */
539 drop_parameters(s2
, nparam
, 1);
544 for (i
= 0; i
< n
; ++i
) {
546 t1
= extract_term(s1
, nparam
, i
);
547 t2
= extract_term(s2
, nparam
, i
);
556 drop_parameters(s
, nparam
, 1);
560 /* Perform summation over a product of factors F, obtained using
561 * variable transformation T from the original problem specification.
563 * We first perform the corresponding transformation on the polynomial E,
564 * compute the common context over all factors and then perform
565 * the actual summation over the factors.
567 static evalue
*sum_product(Polyhedron
*F
, evalue
*E
, Matrix
*T
, unsigned nparam
,
568 struct barvinok_options
*options
)
572 unsigned nvar
= T
->NbRows
;
576 assert(nvar
== T
->NbColumns
);
577 T2
= Matrix_Alloc(nvar
+1, nvar
+1);
578 for (i
= 0; i
< nvar
; ++i
)
579 Vector_Copy(T
->p
[i
], T2
->p
[i
], nvar
);
580 value_set_si(T2
->p
[nvar
][nvar
], 1);
582 transform_polynomial(E
, T2
, NULL
, nvar
, nparam
, nvar
, nparam
);
584 C
= Factor_Context(F
, nparam
, options
->MaxRays
);
585 if (F
->Dimension
== nparam
) {
591 sum
= sum_factors(F
, C
, E
, nvar
, 0, options
);
599 /* Add two constraints corresponding to floor = floor(e/d),
602 * -e + d t + d-1 >= 0
604 * e is assumed to be an affine expression.
606 Polyhedron
*add_floor_var(Polyhedron
*P
, unsigned nvar
, const evalue
*floor
,
607 struct barvinok_options
*options
)
610 unsigned dim
= P
->Dimension
+1;
611 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
+2, 2+dim
);
613 Value
*d
= &M
->p
[0][1+nvar
];
614 evalue_extract_affine(floor
, M
->p
[0]+1, M
->p
[0]+1+dim
, d
);
615 value_oppose(*d
, *d
);
616 value_set_si(M
->p
[0][0], 1);
617 value_set_si(M
->p
[1][0], 1);
618 Vector_Oppose(M
->p
[0]+1, M
->p
[1]+1, M
->NbColumns
-1);
619 value_subtract(M
->p
[1][1+dim
], M
->p
[1][1+dim
], *d
);
620 value_decrement(M
->p
[1][1+dim
], M
->p
[1][1+dim
]);
622 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
623 Vector_Copy(P
->Constraint
[i
], M
->p
[i
+2], 1+nvar
);
624 Vector_Copy(P
->Constraint
[i
]+1+nvar
, M
->p
[i
+2]+1+nvar
+1, dim
-nvar
-1+1);
627 CP
= Constraints2Polyhedron(M
, options
->MaxRays
);
632 static evalue
*evalue_add(evalue
*a
, evalue
*b
)
643 /* Compute sum of a step-polynomial over a polytope by grouping
644 * terms containing the same floor-expressions and introducing
645 * new variables for each such expression.
646 * In particular, while there is any floor-expression left,
647 * the step-polynomial is split into a polynomial containing
648 * the expression, which is then converted to a new variable,
649 * and a polynomial not containing the expression.
651 static evalue
*sum_step_polynomial(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
652 struct barvinok_options
*options
)
659 while ((floor
= evalue_outer_floor(cur
))) {
662 evalue
*converted_floor
;
664 /* Ignore floors that do not depend on variables. */
665 if (value_notzero_p(floor
->d
) || floor
->x
.p
->pos
>= nvar
+1)
668 converted
= evalue_dup(cur
);
669 converted_floor
= evalue_dup(floor
);
670 evalue_shift_variables(converted
, nvar
, 1);
671 evalue_shift_variables(converted_floor
, nvar
, 1);
672 evalue_replace_floor(converted
, converted_floor
, nvar
);
673 CP
= add_floor_var(P
, nvar
, converted_floor
, options
);
674 evalue_free(converted_floor
);
675 t
= sum_step_polynomial(CP
, converted
, nvar
+1, options
);
676 evalue_free(converted
);
678 sum
= evalue_add(t
, sum
);
681 cur
= evalue_dup(cur
);
682 evalue_drop_floor(cur
, floor
);
686 evalue_floor2frac(cur
);
690 if (EVALUE_IS_ZERO(*cur
))
694 unsigned nparam
= P
->Dimension
- nvar
;
695 Polyhedron
*F
= Polyhedron_Factor(P
, nparam
, &T
, options
->MaxRays
);
697 t
= sum_base(P
, cur
, nvar
, options
);
700 cur
= evalue_dup(cur
);
701 t
= sum_product(F
, cur
, T
, nparam
, options
);
708 return evalue_add(t
, sum
);
711 evalue
*barvinok_sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
712 struct evalue_section_array
*sections
,
713 struct barvinok_options
*options
)
716 return sum_over_polytope_with_equalities(P
, E
, nvar
, sections
, options
);
719 return sum_over_polytope_0D(Polyhedron_Copy(P
), evalue_dup(E
));
721 if (options
->summation
== BV_SUM_BERNOULLI
)
722 return bernoulli_summate(P
, E
, nvar
, sections
, options
);
723 else if (options
->summation
== BV_SUM_BOX
)
724 return box_summate(P
, E
, nvar
, options
);
726 evalue_frac2floor2(E
, 0);
728 return sum_step_polynomial(P
, E
, nvar
, options
);
731 evalue
*barvinok_summate(evalue
*e
, int nvar
, struct barvinok_options
*options
)
734 struct evalue_section_array sections
;
738 if (nvar
== 0 || EVALUE_IS_ZERO(*e
))
739 return evalue_dup(e
);
741 assert(value_zero_p(e
->d
));
742 assert(e
->x
.p
->type
== partition
);
744 evalue_section_array_init(§ions
);
747 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
749 for (D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]); D
; D
= D
->next
) {
750 Polyhedron
*next
= D
->next
;
754 tmp
= barvinok_sum_over_polytope(D
, &e
->x
.p
->arr
[2*i
+1], nvar
,
770 static __isl_give isl_pw_qpolynomial
*add_unbounded_guarded_qp(
771 __isl_take isl_pw_qpolynomial
*sum
,
772 __isl_take isl_basic_set
*bset
, __isl_take isl_qpolynomial
*qp
)
776 if (!sum
|| !bset
|| !qp
)
779 zero
= isl_qpolynomial_is_zero(qp
);
786 isl_pw_qpolynomial
*pwqp
;
788 space
= isl_pw_qpolynomial_get_domain_space(sum
);
789 set
= isl_set_from_basic_set(isl_basic_set_copy(bset
));
790 set
= isl_map_domain(isl_map_from_range(set
));
791 set
= isl_set_reset_space(set
, isl_space_copy(space
));
792 pwqp
= isl_pw_qpolynomial_alloc(set
,
793 isl_qpolynomial_nan_on_domain(space
));
794 sum
= isl_pw_qpolynomial_add(sum
, pwqp
);
797 isl_basic_set_free(bset
);
798 isl_qpolynomial_free(qp
);
801 isl_basic_set_free(bset
);
802 isl_qpolynomial_free(qp
);
803 isl_pw_qpolynomial_free(sum
);
807 struct barvinok_summate_data
{
810 isl_pw_qpolynomial
*sum
;
814 struct evalue_section_array sections
;
815 struct barvinok_options
*options
;
818 static isl_stat
add_basic_guarded_qp(__isl_take isl_basic_set
*bset
, void *user
)
820 struct barvinok_summate_data
*data
= user
;
823 isl_pw_qpolynomial
*pwqp
;
825 unsigned nvar
= isl_basic_set_dim(bset
, isl_dim_set
);
829 return isl_stat_error
;
831 bounded
= isl_basic_set_is_bounded(bset
);
836 data
->sum
= add_unbounded_guarded_qp(data
->sum
, bset
,
837 isl_qpolynomial_copy(data
->qp
));
841 space
= isl_space_params(isl_basic_set_get_space(bset
));
843 P
= isl_basic_set_to_polylib(bset
);
844 tmp
= barvinok_sum_over_polytope(P
, data
->e
, nvar
,
845 &data
->sections
, data
->options
);
848 pwqp
= isl_pw_qpolynomial_from_evalue(space
, tmp
);
850 pwqp
= isl_pw_qpolynomial_reset_domain_space(pwqp
,
851 isl_space_domain(isl_space_copy(data
->space
)));
852 data
->sum
= isl_pw_qpolynomial_add(data
->sum
, pwqp
);
854 isl_basic_set_free(bset
);
858 isl_basic_set_free(bset
);
859 return isl_stat_error
;
862 static isl_stat
add_guarded_qp(__isl_take isl_set
*set
,
863 __isl_take isl_qpolynomial
*qp
, void *user
)
866 struct barvinok_summate_data
*data
= user
;
873 if (data
->wrapping
) {
874 unsigned nparam
= isl_set_dim(set
, isl_dim_param
);
875 isl_qpolynomial
*qp2
= isl_qpolynomial_copy(qp
);
876 set
= isl_set_move_dims(set
, isl_dim_param
, nparam
,
877 isl_dim_set
, 0, data
->n_in
);
878 qp2
= isl_qpolynomial_move_dims(qp2
, isl_dim_param
, nparam
,
879 isl_dim_in
, 0, data
->n_in
);
880 data
->e
= isl_qpolynomial_to_evalue(qp2
);
881 isl_qpolynomial_free(qp2
);
883 data
->e
= isl_qpolynomial_to_evalue(qp
);
887 evalue_section_array_init(&data
->sections
);
889 set
= isl_set_make_disjoint(set
);
890 set
= isl_set_compute_divs(set
);
892 r
= isl_set_foreach_basic_set(set
, &add_basic_guarded_qp
, data
);
894 free(data
->sections
.s
);
896 evalue_free(data
->e
);
899 isl_qpolynomial_free(qp
);
904 isl_qpolynomial_free(qp
);
905 return isl_stat_error
;
908 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_sum(
909 __isl_take isl_pw_qpolynomial
*pwqp
)
912 struct barvinok_summate_data data
;
913 int options_allocated
= 0;
923 nvar
= isl_pw_qpolynomial_dim(pwqp
, isl_dim_set
);
925 data
.space
= isl_pw_qpolynomial_get_domain_space(pwqp
);
928 if (isl_space_is_params(data
.space
))
929 isl_die(isl_pw_qpolynomial_get_ctx(pwqp
), isl_error_invalid
,
930 "input polynomial has no domain", goto error
);
931 data
.wrapping
= isl_space_is_wrapping(data
.space
);
933 data
.space
= isl_space_unwrap(data
.space
);
934 data
.n_in
= isl_space_dim(data
.space
, isl_dim_in
);
935 nvar
= isl_space_dim(data
.space
, isl_dim_out
);
939 data
.space
= isl_space_domain(data
.space
);
941 return isl_pw_qpolynomial_reset_domain_space(pwqp
, data
.space
);
943 data
.space
= isl_space_from_domain(data
.space
);
944 data
.space
= isl_space_add_dims(data
.space
, isl_dim_out
, 1);
945 data
.sum
= isl_pw_qpolynomial_zero(isl_space_copy(data
.space
));
947 ctx
= isl_pw_qpolynomial_get_ctx(pwqp
);
948 data
.options
= isl_ctx_peek_barvinok_options(ctx
);
950 data
.options
= barvinok_options_new_with_defaults();
951 options_allocated
= 1;
954 if (isl_pw_qpolynomial_foreach_lifted_piece(pwqp
,
955 add_guarded_qp
, &data
) < 0)
958 if (options_allocated
)
959 barvinok_options_free(data
.options
);
961 isl_space_free(data
.space
);
963 isl_pw_qpolynomial_free(pwqp
);
967 if (options_allocated
)
968 barvinok_options_free(data
.options
);
969 isl_pw_qpolynomial_free(pwqp
);
970 isl_space_free(data
.space
);
971 isl_pw_qpolynomial_free(data
.sum
);
975 static isl_stat
pw_qpolynomial_sum(__isl_take isl_pw_qpolynomial
*pwqp
,
978 isl_union_pw_qpolynomial
**res
= (isl_union_pw_qpolynomial
**)user
;
979 isl_pw_qpolynomial
*sum
;
980 isl_union_pw_qpolynomial
*upwqp
;
982 sum
= isl_pw_qpolynomial_sum(pwqp
);
983 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(sum
);
984 *res
= isl_union_pw_qpolynomial_add(*res
, upwqp
);
989 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_sum(
990 __isl_take isl_union_pw_qpolynomial
*upwqp
)
993 isl_union_pw_qpolynomial
*res
;
995 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
996 res
= isl_union_pw_qpolynomial_zero(space
);
997 if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp
,
998 &pw_qpolynomial_sum
, &res
) < 0)
1000 isl_union_pw_qpolynomial_free(upwqp
);
1004 isl_union_pw_qpolynomial_free(upwqp
);
1005 isl_union_pw_qpolynomial_free(res
);
1009 static int join_compatible(__isl_keep isl_space
*space1
,
1010 __isl_keep isl_space
*space2
)
1013 m
= isl_space_has_equal_params(space1
, space2
);
1016 return isl_space_tuple_is_equal(space1
, isl_dim_out
,
1017 space2
, isl_dim_in
);
1020 /* Compute the intersection of the range of the map and the domain
1021 * of the piecewise quasipolynomial and then sum the associated
1022 * quasipolynomial over all elements in this intersection.
1024 * We first introduce some unconstrained dimensions in the
1025 * piecewise quasipolynomial, intersect the resulting domain
1026 * with the wrapped map and then compute the sum.
1028 __isl_give isl_pw_qpolynomial
*isl_map_apply_pw_qpolynomial(
1029 __isl_take isl_map
*map
, __isl_take isl_pw_qpolynomial
*pwqp
)
1033 isl_space
*map_space
;
1034 isl_space
*pwqp_space
;
1038 ctx
= isl_map_get_ctx(map
);
1042 map_space
= isl_map_get_space(map
);
1043 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1044 ok
= join_compatible(map_space
, pwqp_space
);
1045 isl_space_free(map_space
);
1046 isl_space_free(pwqp_space
);
1048 isl_die(ctx
, isl_error_invalid
, "incompatible dimensions",
1051 n_in
= isl_map_dim(map
, isl_dim_in
);
1052 pwqp
= isl_pw_qpolynomial_insert_dims(pwqp
, isl_dim_in
, 0, n_in
);
1054 dom
= isl_map_wrap(map
);
1055 pwqp
= isl_pw_qpolynomial_reset_domain_space(pwqp
,
1056 isl_set_get_space(dom
));
1058 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, dom
);
1059 pwqp
= isl_pw_qpolynomial_sum(pwqp
);
1064 isl_pw_qpolynomial_free(pwqp
);
1068 __isl_give isl_pw_qpolynomial
*isl_set_apply_pw_qpolynomial(
1069 __isl_take isl_set
*set
, __isl_take isl_pw_qpolynomial
*pwqp
)
1073 map
= isl_map_from_range(set
);
1074 pwqp
= isl_map_apply_pw_qpolynomial(map
, pwqp
);
1075 pwqp
= isl_pw_qpolynomial_project_domain_on_params(pwqp
);
1079 struct barvinok_apply_data
{
1080 isl_union_pw_qpolynomial
*upwqp
;
1081 isl_union_pw_qpolynomial
*res
;
1085 static isl_stat
pw_qpolynomial_apply(__isl_take isl_pw_qpolynomial
*pwqp
,
1088 isl_space
*map_space
;
1089 isl_space
*pwqp_space
;
1090 struct barvinok_apply_data
*data
= user
;
1093 map_space
= isl_map_get_space(data
->map
);
1094 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1095 ok
= join_compatible(map_space
, pwqp_space
);
1096 isl_space_free(map_space
);
1097 isl_space_free(pwqp_space
);
1100 isl_union_pw_qpolynomial
*upwqp
;
1102 pwqp
= isl_map_apply_pw_qpolynomial(isl_map_copy(data
->map
),
1104 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(pwqp
);
1105 data
->res
= isl_union_pw_qpolynomial_add(data
->res
, upwqp
);
1107 isl_pw_qpolynomial_free(pwqp
);
1112 static isl_stat
map_apply(__isl_take isl_map
*map
, void *user
)
1114 struct barvinok_apply_data
*data
= user
;
1118 r
= isl_union_pw_qpolynomial_foreach_pw_qpolynomial(data
->upwqp
,
1119 &pw_qpolynomial_apply
, data
);
1125 __isl_give isl_union_pw_qpolynomial
*isl_union_map_apply_union_pw_qpolynomial(
1126 __isl_take isl_union_map
*umap
,
1127 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1130 struct barvinok_apply_data data
;
1132 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1133 isl_union_map_get_space(umap
));
1134 umap
= isl_union_map_align_params(umap
,
1135 isl_union_pw_qpolynomial_get_space(upwqp
));
1138 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
1139 data
.res
= isl_union_pw_qpolynomial_zero(space
);
1140 if (isl_union_map_foreach_map(umap
, &map_apply
, &data
) < 0)
1143 isl_union_map_free(umap
);
1144 isl_union_pw_qpolynomial_free(upwqp
);
1148 isl_union_map_free(umap
);
1149 isl_union_pw_qpolynomial_free(upwqp
);
1150 isl_union_pw_qpolynomial_free(data
.res
);
1154 struct barvinok_apply_set_data
{
1155 isl_union_pw_qpolynomial
*upwqp
;
1156 isl_union_pw_qpolynomial
*res
;
1160 static isl_stat
pw_qpolynomial_apply_set(__isl_take isl_pw_qpolynomial
*pwqp
,
1163 isl_space
*set_space
;
1164 isl_space
*pwqp_space
;
1165 struct barvinok_apply_set_data
*data
= user
;
1168 set_space
= isl_set_get_space(data
->set
);
1169 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1170 ok
= join_compatible(set_space
, pwqp_space
);
1171 isl_space_free(set_space
);
1172 isl_space_free(pwqp_space
);
1175 isl_union_pw_qpolynomial
*upwqp
;
1177 pwqp
= isl_set_apply_pw_qpolynomial(isl_set_copy(data
->set
),
1179 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(pwqp
);
1180 data
->res
= isl_union_pw_qpolynomial_add(data
->res
, upwqp
);
1182 isl_pw_qpolynomial_free(pwqp
);
1187 static isl_stat
set_apply(__isl_take isl_set
*set
, void *user
)
1189 struct barvinok_apply_set_data
*data
= user
;
1193 r
= isl_union_pw_qpolynomial_foreach_pw_qpolynomial(data
->upwqp
,
1194 &pw_qpolynomial_apply_set
, data
);
1200 __isl_give isl_union_pw_qpolynomial
*isl_union_set_apply_union_pw_qpolynomial(
1201 __isl_take isl_union_set
*uset
,
1202 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1205 struct barvinok_apply_set_data data
;
1207 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1208 isl_union_set_get_space(uset
));
1209 uset
= isl_union_set_align_params(uset
,
1210 isl_union_pw_qpolynomial_get_space(upwqp
));
1213 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
1214 data
.res
= isl_union_pw_qpolynomial_zero(space
);
1215 if (isl_union_set_foreach_set(uset
, &set_apply
, &data
) < 0)
1218 isl_union_set_free(uset
);
1219 isl_union_pw_qpolynomial_free(upwqp
);
1223 isl_union_set_free(uset
);
1224 isl_union_pw_qpolynomial_free(upwqp
);
1225 isl_union_pw_qpolynomial_free(data
.res
);
1229 evalue
*evalue_sum(evalue
*E
, int nvar
, unsigned MaxRays
)
1232 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1233 options
->MaxRays
= MaxRays
;
1234 sum
= barvinok_summate(E
, nvar
, options
);
1235 barvinok_options_free(options
);
1239 evalue
*esum(evalue
*e
, int nvar
)
1242 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1243 sum
= barvinok_summate(e
, nvar
, options
);
1244 barvinok_options_free(options
);
1248 /* Turn unweighted counting problem into "weighted" counting problem
1249 * with weight equal to 1 and call barvinok_summate on this weighted problem.
1251 evalue
*barvinok_summate_unweighted(Polyhedron
*P
, Polyhedron
*C
,
1252 struct barvinok_options
*options
)
1258 if (emptyQ(P
) || emptyQ(C
))
1259 return evalue_zero();
1261 CA
= align_context(C
, P
->Dimension
, options
->MaxRays
);
1262 D
= DomainIntersection(P
, CA
, options
->MaxRays
);
1267 return evalue_zero();
1271 e
.x
.p
= new_enode(partition
, 2, P
->Dimension
);
1272 EVALUE_SET_DOMAIN(e
.x
.p
->arr
[0], D
);
1273 evalue_set_si(&e
.x
.p
->arr
[1], 1, 1);
1274 sum
= barvinok_summate(&e
, P
->Dimension
- C
->Dimension
, options
);
1275 free_evalue_refs(&e
);