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"
17 #include "section_array.h"
18 #include "remove_equalities.h"
20 extern evalue
*evalue_outer_floor(evalue
*e
);
21 extern int evalue_replace_floor(evalue
*e
, const evalue
*floor
, int var
);
22 extern void evalue_drop_floor(evalue
*e
, const evalue
*floor
);
24 #define ALLOC(type) (type*)malloc(sizeof(type))
25 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
27 /* Apply the variable transformation specified by T and CP on
28 * the polynomial e. T expresses the old variables in terms
29 * of the new variables (and optionally also the new parameters),
30 * while CP expresses the old parameters in terms of the new
33 static void transform_polynomial(evalue
*E
, Matrix
*T
, Matrix
*CP
,
34 unsigned nvar
, unsigned nparam
,
35 unsigned new_nvar
, unsigned new_nparam
)
40 subs
= ALLOCN(evalue
*, nvar
+nparam
);
42 for (j
= 0; j
< nvar
; ++j
) {
44 subs
[j
] = affine2evalue(T
->p
[j
], T
->p
[T
->NbRows
-1][T
->NbColumns
-1],
47 subs
[j
] = evalue_var(j
);
49 for (j
= 0; j
< nparam
; ++j
) {
51 subs
[nvar
+j
] = affine2evalue(CP
->p
[j
], CP
->p
[nparam
][new_nparam
],
54 subs
[nvar
+j
] = evalue_var(j
);
55 evalue_shift_variables(subs
[nvar
+j
], 0, new_nvar
);
58 evalue_substitute(E
, subs
);
61 for (j
= 0; j
< nvar
+nparam
; ++j
)
66 /* Compute the sum of the quasi-polynomial E
67 * over a 0D (non-empty, but possibly parametric) polytope P.
71 * We simply return a partition evalue with P as domain and E as value.
73 static evalue
*sum_over_polytope_0D(Polyhedron
*P
, evalue
*E
)
79 sum
->x
.p
= new_enode(partition
, 2, P
->Dimension
);
80 EVALUE_SET_DOMAIN(sum
->x
.p
->arr
[0], P
);
81 value_clear(sum
->x
.p
->arr
[1].d
);
82 sum
->x
.p
->arr
[1] = *E
;
88 static evalue
*sum_with_equalities(Polyhedron
*P
, evalue
*E
,
89 unsigned nvar
, struct evalue_section_array
*sections
,
90 struct barvinok_options
*options
,
91 evalue
*(*base
)(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
92 struct evalue_section_array
*sections
,
93 struct barvinok_options
*options
))
95 unsigned dim
= P
->Dimension
;
96 unsigned new_dim
, new_nparam
;
97 Matrix
*T
= NULL
, *CP
= NULL
;
101 return evalue_zero();
105 remove_all_equalities(&P
, NULL
, &CP
, &T
, dim
-nvar
, options
->MaxRays
);
109 return evalue_zero();
112 new_nparam
= CP
? CP
->NbColumns
-1 : dim
- nvar
;
113 new_dim
= T
? T
->NbColumns
-1 : nvar
+ new_nparam
;
115 /* We can avoid these substitutions if E is a constant */
117 transform_polynomial(E
, T
, CP
, nvar
, dim
-nvar
,
118 new_dim
-new_nparam
, new_nparam
);
120 if (new_dim
-new_nparam
> 0) {
121 sum
= base(P
, E
, new_dim
-new_nparam
, sections
, options
);
125 sum
= sum_over_polytope_0D(P
, E
);
129 evalue_backsubstitute(sum
, CP
, options
->MaxRays
);
139 static evalue
*sum_over_polytope_with_equalities(Polyhedron
*P
, evalue
*E
,
140 unsigned nvar
, struct evalue_section_array
*sections
,
141 struct barvinok_options
*options
)
143 return sum_with_equalities(P
, E
, nvar
, sections
, options
,
144 &barvinok_sum_over_polytope
);
147 static evalue
*sum_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
148 struct barvinok_options
*options
);
150 static evalue
*sum_base_wrap(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
151 struct evalue_section_array
*sections
, struct barvinok_options
*options
)
153 return sum_base(P
, E
, nvar
, options
);
156 static evalue
*sum_base_with_equalities(Polyhedron
*P
, evalue
*E
,
157 unsigned nvar
, struct barvinok_options
*options
)
159 return sum_with_equalities(P
, E
, nvar
, NULL
, options
, &sum_base_wrap
);
162 /* The substitutions in sum_step_polynomial may have reintroduced equalities
163 * (in particular, one of the floor expressions may be equal to one of
164 * the variables), so we need to check for them again.
166 static evalue
*sum_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
167 struct barvinok_options
*options
)
170 return sum_base_with_equalities(P
, E
, nvar
, options
);
171 if (options
->summation
== BV_SUM_EULER
)
172 return euler_summate(P
, E
, nvar
, options
);
173 else if (options
->summation
== BV_SUM_LAURENT
)
174 return laurent_summate(P
, E
, nvar
, options
);
175 else if (options
->summation
== BV_SUM_LAURENT_OLD
)
176 return laurent_summate_old(P
, E
, nvar
, options
);
180 /* Count the number of non-zero terms in e when viewed as a polynomial
181 * in only the first nvar variables. "count" is the number counted
184 static int evalue_count_terms(const evalue
*e
, unsigned nvar
, int count
)
188 if (EVALUE_IS_ZERO(*e
))
191 if (value_zero_p(e
->d
))
192 assert(e
->x
.p
->type
== polynomial
);
193 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1)
196 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
197 count
= evalue_count_terms(&e
->x
.p
->arr
[i
], nvar
, count
);
202 /* Create placeholder structure for unzipping.
203 * A "polynomial" is created with size terms in variable pos,
204 * with each term having itself as coefficient.
206 static evalue
*create_placeholder(int size
, int pos
)
209 evalue
*E
= ALLOC(evalue
);
211 E
->x
.p
= new_enode(polynomial
, size
, pos
+1);
212 for (i
= 0; i
< size
; ++i
) {
213 E
->x
.p
->arr
[i
].x
.p
= new_enode(polynomial
, i
+1, pos
+1);
214 for (j
= 0; j
< i
; ++j
)
215 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[j
], 0, 1);
216 evalue_set_si(&E
->x
.p
->arr
[i
].x
.p
->arr
[i
], 1, 1);
221 /* Interchange each non-zero term in e (when viewed as a polynomial
222 * in only the first nvar variables) with a placeholder in ph (created
223 * by create_placeholder), resulting in two polynomials in the
224 * placeholder variable such that for each non-zero term in e
225 * there is a power of the placeholder variable such that the factors
226 * in the first nvar variables form the coefficient of that power in
227 * the first polynomial (e) and the factors in the remaining variables
228 * form the coefficient of that power in the second polynomial (ph).
230 static int evalue_unzip_terms(evalue
*e
, evalue
*ph
, unsigned nvar
, int count
)
234 if (EVALUE_IS_ZERO(*e
))
237 if (value_zero_p(e
->d
))
238 assert(e
->x
.p
->type
== polynomial
);
239 if (value_notzero_p(e
->d
) || e
->x
.p
->pos
>= nvar
+1) {
241 *e
= ph
->x
.p
->arr
[count
];
242 ph
->x
.p
->arr
[count
] = t
;
246 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
247 count
= evalue_unzip_terms(&e
->x
.p
->arr
[i
], ph
, nvar
, count
);
252 /* Remove n variables at pos (0-based) from the polyhedron P.
253 * Each of these variables is assumed to be completely free,
254 * i.e., there is a line in the polyhedron corresponding to
255 * each of these variables.
257 static Polyhedron
*Polyhedron_Remove_Columns(Polyhedron
*P
, unsigned pos
,
261 unsigned NbConstraints
= 0;
268 assert(pos
<= P
->Dimension
);
270 if (POL_HAS(P
, POL_INEQUALITIES
))
271 NbConstraints
= P
->NbConstraints
;
272 if (POL_HAS(P
, POL_POINTS
))
273 NbRays
= P
->NbRays
- n
;
275 Q
= Polyhedron_Alloc(P
->Dimension
- n
, NbConstraints
, NbRays
);
276 if (POL_HAS(P
, POL_INEQUALITIES
)) {
278 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
279 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
280 Vector_Copy(P
->Constraint
[i
]+1+pos
+n
, Q
->Constraint
[i
]+1+pos
,
284 if (POL_HAS(P
, POL_POINTS
)) {
285 Q
->NbBid
= P
->NbBid
- n
;
286 for (i
= 0; i
< n
; ++i
)
287 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
288 for (i
= 0, j
= 0; i
< P
->NbRays
; ++i
) {
289 int line
= First_Non_Zero(P
->Ray
[i
], 1+P
->Dimension
+1);
291 if (line
-1 >= pos
&& line
-1 < pos
+n
) {
296 assert(i
-j
< Q
->NbRays
);
297 Vector_Copy(P
->Ray
[i
], Q
->Ray
[i
-j
], 1+pos
);
298 Vector_Copy(P
->Ray
[i
]+1+pos
+n
, Q
->Ray
[i
-j
]+1+pos
,
302 POL_SET(Q
, POL_VALID
);
303 if (POL_HAS(P
, POL_INEQUALITIES
))
304 POL_SET(Q
, POL_INEQUALITIES
);
305 if (POL_HAS(P
, POL_POINTS
))
306 POL_SET(Q
, POL_POINTS
);
307 if (POL_HAS(P
, POL_VERTICES
))
308 POL_SET(Q
, POL_VERTICES
);
312 /* Remove n variables at pos (0-based) from the union of polyhedra P.
313 * Each of these variables is assumed to be completely free,
314 * i.e., there is a line in the polyhedron corresponding to
315 * each of these variables.
317 static Polyhedron
*Domain_Remove_Columns(Polyhedron
*P
, unsigned pos
,
321 Polyhedron
**next
= &R
;
323 for (; P
; P
= P
->next
) {
324 *next
= Polyhedron_Remove_Columns(P
, pos
, n
);
325 next
= &(*next
)->next
;
330 /* Drop n parameters starting at first from partition evalue e */
331 static void drop_parameters(evalue
*e
, int first
, int n
)
335 if (EVALUE_IS_ZERO(*e
))
338 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
339 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
340 Polyhedron
*P
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
341 Polyhedron
*Q
= Domain_Remove_Columns(P
, first
, n
);
342 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[2*i
], Q
);
344 evalue_shift_variables(&e
->x
.p
->arr
[2*i
+1], first
, -n
);
349 static void extract_term_into(const evalue
*src
, int var
, int exp
, evalue
*dst
)
353 if (value_notzero_p(src
->d
) ||
354 src
->x
.p
->type
!= polynomial
||
355 src
->x
.p
->pos
> var
+1) {
357 evalue_copy(dst
, src
);
359 evalue_set_si(dst
, 0, 1);
363 if (src
->x
.p
->pos
== var
+1) {
364 if (src
->x
.p
->size
> exp
)
365 evalue_copy(dst
, &src
->x
.p
->arr
[exp
]);
367 evalue_set_si(dst
, 0, 1);
371 dst
->x
.p
= new_enode(polynomial
, src
->x
.p
->size
, src
->x
.p
->pos
);
372 for (i
= 0; i
< src
->x
.p
->size
; ++i
)
373 extract_term_into(&src
->x
.p
->arr
[i
], var
, exp
,
377 /* Extract the coefficient of var^exp.
379 static evalue
*extract_term(const evalue
*e
, int var
, int exp
)
384 if (EVALUE_IS_ZERO(*e
))
385 return evalue_zero();
387 assert(value_zero_p(e
->d
) && e
->x
.p
->type
== partition
);
390 res
->x
.p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
391 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
392 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
393 Domain_Copy(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])));
394 extract_term_into(&e
->x
.p
->arr
[2*i
+1], var
, exp
,
395 &res
->x
.p
->arr
[2*i
+1]);
396 reduce_evalue(&res
->x
.p
->arr
[2*i
+1]);
401 /* Insert n free variables at pos (0-based) in the polyhedron P.
403 static Polyhedron
*Polyhedron_Insert_Columns(Polyhedron
*P
, unsigned pos
,
407 unsigned NbConstraints
= 0;
416 assert(pos
<= P
->Dimension
);
418 if (POL_HAS(P
, POL_INEQUALITIES
))
419 NbConstraints
= P
->NbConstraints
;
420 if (POL_HAS(P
, POL_POINTS
))
421 NbRays
= P
->NbRays
+ n
;
423 Q
= Polyhedron_Alloc(P
->Dimension
+n
, NbConstraints
, NbRays
);
424 if (POL_HAS(P
, POL_INEQUALITIES
)) {
426 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
427 Vector_Copy(P
->Constraint
[i
], Q
->Constraint
[i
], 1+pos
);
428 Vector_Copy(P
->Constraint
[i
]+1+pos
, Q
->Constraint
[i
]+1+pos
+n
,
432 if (POL_HAS(P
, POL_POINTS
)) {
433 Q
->NbBid
= P
->NbBid
+ n
;
434 for (i
= 0; i
< n
; ++i
)
435 value_set_si(Q
->Ray
[i
][1+pos
+i
], 1);
436 for (i
= 0; i
< P
->NbRays
; ++i
) {
437 Vector_Copy(P
->Ray
[i
], Q
->Ray
[n
+i
], 1+pos
);
438 Vector_Copy(P
->Ray
[i
]+1+pos
, Q
->Ray
[n
+i
]+1+pos
+n
,
442 POL_SET(Q
, POL_VALID
);
443 if (POL_HAS(P
, POL_INEQUALITIES
))
444 POL_SET(Q
, POL_INEQUALITIES
);
445 if (POL_HAS(P
, POL_POINTS
))
446 POL_SET(Q
, POL_POINTS
);
447 if (POL_HAS(P
, POL_VERTICES
))
448 POL_SET(Q
, POL_VERTICES
);
452 /* Perform summation of e over a list of 1 or more factors F, with context C.
453 * nvar is the total number of variables in the remaining factors.
454 * extra is the number of placeholder parameters introduced in e,
455 * but not (yet) in F or C.
457 * If there is only one factor left, F is intersected with the
458 * context C, the placeholder variables are added, and then
459 * e is summed over the resulting parametric polytope.
461 * If there is more than one factor left, we create two polynomials
462 * in a new placeholder variable (which is placed after the regular
463 * parameters, but before any previously introduced placeholder
464 * variables) that has the factors of the variables in the first
465 * factor of F and the factor of the remaining variables of
466 * each term as its coefficients.
467 * These two polynomials are then summed over their domains
468 * and afterwards the results are combined and the placeholder
469 * variable is removed again.
471 static evalue
*sum_factors(Polyhedron
*F
, Polyhedron
*C
, evalue
*e
,
472 unsigned nvar
, unsigned extra
,
473 struct barvinok_options
*options
)
475 unsigned nparam
= C
->Dimension
;
476 unsigned F_var
= F
->Dimension
- C
->Dimension
;
482 Polyhedron
*CA
= align_context(C
, nvar
+nparam
, options
->MaxRays
);
483 Polyhedron
*P
= DomainIntersection(F
, CA
, options
->MaxRays
);
484 Polyhedron
*Q
= Polyhedron_Insert_Columns(P
, nvar
+nparam
, extra
);
488 evalue
*sum
= sum_base(Q
, e
, nvar
, options
);
493 n
= evalue_count_terms(e
, F_var
, 0);
494 ph
= create_placeholder(n
, nvar
+nparam
);
495 evalue_shift_variables(e
, nvar
+nparam
, 1);
496 evalue_unzip_terms(e
, ph
, F_var
, 0);
497 evalue_shift_variables(e
, nvar
, -(nvar
-F_var
));
498 evalue_reorder_terms(ph
);
499 evalue_shift_variables(ph
, 0, -F_var
);
501 s2
= sum_factors(F
->next
, C
, ph
, nvar
-F_var
, extra
+1, options
);
504 s1
= sum_factors(F
, C
, e
, F_var
, extra
+1, options
);
507 /* remove placeholder "polynomial" */
511 drop_parameters(s2
, nparam
, 1);
516 for (i
= 0; i
< n
; ++i
) {
518 t1
= extract_term(s1
, nparam
, i
);
519 t2
= extract_term(s2
, nparam
, i
);
528 drop_parameters(s
, nparam
, 1);
532 /* Perform summation over a product of factors F, obtained using
533 * variable transformation T from the original problem specification.
535 * We first perform the corresponding transformation on the polynomial E,
536 * compute the common context over all factors and then perform
537 * the actual summation over the factors.
539 static evalue
*sum_product(Polyhedron
*F
, evalue
*E
, Matrix
*T
, unsigned nparam
,
540 struct barvinok_options
*options
)
544 unsigned nvar
= T
->NbRows
;
548 assert(nvar
== T
->NbColumns
);
549 T2
= Matrix_Alloc(nvar
+1, nvar
+1);
550 for (i
= 0; i
< nvar
; ++i
)
551 Vector_Copy(T
->p
[i
], T2
->p
[i
], nvar
);
552 value_set_si(T2
->p
[nvar
][nvar
], 1);
554 transform_polynomial(E
, T2
, NULL
, nvar
, nparam
, nvar
, nparam
);
556 C
= Factor_Context(F
, nparam
, options
->MaxRays
);
557 if (F
->Dimension
== nparam
) {
563 sum
= sum_factors(F
, C
, E
, nvar
, 0, options
);
571 /* Add two constraints corresponding to floor = floor(e/d),
574 * -e + d t + d-1 >= 0
576 * e is assumed to be an affine expression.
578 Polyhedron
*add_floor_var(Polyhedron
*P
, unsigned nvar
, const evalue
*floor
,
579 struct barvinok_options
*options
)
582 unsigned dim
= P
->Dimension
+1;
583 Matrix
*M
= Matrix_Alloc(P
->NbConstraints
+2, 2+dim
);
585 Value
*d
= &M
->p
[0][1+nvar
];
586 evalue_extract_affine(floor
, M
->p
[0]+1, M
->p
[0]+1+dim
, d
);
587 value_oppose(*d
, *d
);
588 value_set_si(M
->p
[0][0], 1);
589 value_set_si(M
->p
[1][0], 1);
590 Vector_Oppose(M
->p
[0]+1, M
->p
[1]+1, M
->NbColumns
-1);
591 value_subtract(M
->p
[1][1+dim
], M
->p
[1][1+dim
], *d
);
592 value_decrement(M
->p
[1][1+dim
], M
->p
[1][1+dim
]);
594 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
595 Vector_Copy(P
->Constraint
[i
], M
->p
[i
+2], 1+nvar
);
596 Vector_Copy(P
->Constraint
[i
]+1+nvar
, M
->p
[i
+2]+1+nvar
+1, dim
-nvar
-1+1);
599 CP
= Constraints2Polyhedron(M
, options
->MaxRays
);
604 static evalue
*evalue_add(evalue
*a
, evalue
*b
)
615 /* Compute sum of a step-polynomial over a polytope by grouping
616 * terms containing the same floor-expressions and introducing
617 * new variables for each such expression.
618 * In particular, while there is any floor-expression left,
619 * the step-polynomial is split into a polynomial containing
620 * the expression, which is then converted to a new variable,
621 * and a polynomial not containing the expression.
623 static evalue
*sum_step_polynomial(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
624 struct barvinok_options
*options
)
631 while ((floor
= evalue_outer_floor(cur
))) {
634 evalue
*converted_floor
;
636 /* Ignore floors that do not depend on variables. */
637 if (value_notzero_p(floor
->d
) || floor
->x
.p
->pos
>= nvar
+1)
640 converted
= evalue_dup(cur
);
641 converted_floor
= evalue_dup(floor
);
642 evalue_shift_variables(converted
, nvar
, 1);
643 evalue_shift_variables(converted_floor
, nvar
, 1);
644 evalue_replace_floor(converted
, converted_floor
, nvar
);
645 CP
= add_floor_var(P
, nvar
, converted_floor
, options
);
646 evalue_free(converted_floor
);
647 t
= sum_step_polynomial(CP
, converted
, nvar
+1, options
);
648 evalue_free(converted
);
650 sum
= evalue_add(t
, sum
);
653 cur
= evalue_dup(cur
);
654 evalue_drop_floor(cur
, floor
);
658 evalue_floor2frac(cur
);
662 if (EVALUE_IS_ZERO(*cur
))
666 unsigned nparam
= P
->Dimension
- nvar
;
667 Polyhedron
*F
= Polyhedron_Factor(P
, nparam
, &T
, options
->MaxRays
);
669 t
= sum_base(P
, cur
, nvar
, options
);
672 cur
= evalue_dup(cur
);
673 t
= sum_product(F
, cur
, T
, nparam
, options
);
680 return evalue_add(t
, sum
);
683 evalue
*barvinok_sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
684 struct evalue_section_array
*sections
,
685 struct barvinok_options
*options
)
688 return sum_over_polytope_with_equalities(P
, E
, nvar
, sections
, options
);
691 return sum_over_polytope_0D(Polyhedron_Copy(P
), evalue_dup(E
));
693 if (options
->summation
== BV_SUM_BERNOULLI
)
694 return bernoulli_summate(P
, E
, nvar
, sections
, options
);
695 else if (options
->summation
== BV_SUM_BOX
)
696 return box_summate(P
, E
, nvar
, options
->MaxRays
);
698 evalue_frac2floor2(E
, 0);
700 return sum_step_polynomial(P
, E
, nvar
, options
);
703 evalue
*barvinok_summate(evalue
*e
, int nvar
, struct barvinok_options
*options
)
706 struct evalue_section_array sections
;
710 if (nvar
== 0 || EVALUE_IS_ZERO(*e
))
711 return evalue_dup(e
);
713 assert(value_zero_p(e
->d
));
714 assert(e
->x
.p
->type
== partition
);
716 evalue_section_array_init(§ions
);
719 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
721 for (D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]); D
; D
= D
->next
) {
722 Polyhedron
*next
= D
->next
;
726 tmp
= barvinok_sum_over_polytope(D
, &e
->x
.p
->arr
[2*i
+1], nvar
,
742 static __isl_give isl_pw_qpolynomial
*add_unbounded_guarded_qp(
743 __isl_take isl_pw_qpolynomial
*sum
,
744 __isl_take isl_basic_set
*bset
, __isl_take isl_qpolynomial
*qp
)
748 if (!sum
|| !bset
|| !qp
)
751 zero
= isl_qpolynomial_is_zero(qp
);
758 isl_pw_qpolynomial
*pwqp
;
760 space
= isl_pw_qpolynomial_get_domain_space(sum
);
761 set
= isl_set_from_basic_set(isl_basic_set_copy(bset
));
762 set
= isl_map_domain(isl_map_from_range(set
));
763 set
= isl_set_reset_space(set
, isl_space_copy(space
));
764 pwqp
= isl_pw_qpolynomial_alloc(set
,
765 isl_qpolynomial_nan_on_domain(space
));
766 sum
= isl_pw_qpolynomial_add(sum
, pwqp
);
769 isl_basic_set_free(bset
);
770 isl_qpolynomial_free(qp
);
773 isl_basic_set_free(bset
);
774 isl_qpolynomial_free(qp
);
775 isl_pw_qpolynomial_free(sum
);
779 struct barvinok_summate_data
{
782 isl_pw_qpolynomial
*sum
;
786 struct evalue_section_array sections
;
787 struct barvinok_options
*options
;
790 static isl_stat
add_basic_guarded_qp(__isl_take isl_basic_set
*bset
, void *user
)
792 struct barvinok_summate_data
*data
= user
;
795 isl_pw_qpolynomial
*pwqp
;
797 unsigned nvar
= isl_basic_set_dim(bset
, isl_dim_set
);
801 return isl_stat_error
;
803 bounded
= isl_basic_set_is_bounded(bset
);
808 data
->sum
= add_unbounded_guarded_qp(data
->sum
, bset
,
809 isl_qpolynomial_copy(data
->qp
));
813 space
= isl_space_params(isl_basic_set_get_space(bset
));
815 P
= isl_basic_set_to_polylib(bset
);
816 tmp
= barvinok_sum_over_polytope(P
, data
->e
, nvar
,
817 &data
->sections
, data
->options
);
820 pwqp
= isl_pw_qpolynomial_from_evalue(space
, tmp
);
822 pwqp
= isl_pw_qpolynomial_reset_domain_space(pwqp
,
823 isl_space_domain(isl_space_copy(data
->space
)));
824 data
->sum
= isl_pw_qpolynomial_add(data
->sum
, pwqp
);
826 isl_basic_set_free(bset
);
830 isl_basic_set_free(bset
);
831 return isl_stat_error
;
834 static isl_stat
add_guarded_qp(__isl_take isl_set
*set
,
835 __isl_take isl_qpolynomial
*qp
, void *user
)
838 struct barvinok_summate_data
*data
= user
;
845 if (data
->wrapping
) {
846 unsigned nparam
= isl_set_dim(set
, isl_dim_param
);
847 isl_qpolynomial
*qp2
= isl_qpolynomial_copy(qp
);
848 set
= isl_set_move_dims(set
, isl_dim_param
, nparam
,
849 isl_dim_set
, 0, data
->n_in
);
850 qp2
= isl_qpolynomial_move_dims(qp2
, isl_dim_param
, nparam
,
851 isl_dim_in
, 0, data
->n_in
);
852 data
->e
= isl_qpolynomial_to_evalue(qp2
);
853 isl_qpolynomial_free(qp2
);
855 data
->e
= isl_qpolynomial_to_evalue(qp
);
859 evalue_section_array_init(&data
->sections
);
861 set
= isl_set_make_disjoint(set
);
862 set
= isl_set_compute_divs(set
);
864 r
= isl_set_foreach_basic_set(set
, &add_basic_guarded_qp
, data
);
866 free(data
->sections
.s
);
868 evalue_free(data
->e
);
871 isl_qpolynomial_free(qp
);
876 isl_qpolynomial_free(qp
);
877 return isl_stat_error
;
880 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_sum(
881 __isl_take isl_pw_qpolynomial
*pwqp
)
884 struct barvinok_summate_data data
;
885 int options_allocated
= 0;
895 nvar
= isl_pw_qpolynomial_dim(pwqp
, isl_dim_set
);
897 data
.space
= isl_pw_qpolynomial_get_domain_space(pwqp
);
900 if (isl_space_is_params(data
.space
))
901 isl_die(isl_pw_qpolynomial_get_ctx(pwqp
), isl_error_invalid
,
902 "input polynomial has no domain", goto error
);
903 data
.wrapping
= isl_space_is_wrapping(data
.space
);
905 data
.space
= isl_space_unwrap(data
.space
);
906 data
.n_in
= isl_space_dim(data
.space
, isl_dim_in
);
907 nvar
= isl_space_dim(data
.space
, isl_dim_out
);
911 data
.space
= isl_space_domain(data
.space
);
913 return isl_pw_qpolynomial_reset_domain_space(pwqp
, data
.space
);
915 data
.space
= isl_space_from_domain(data
.space
);
916 data
.space
= isl_space_add_dims(data
.space
, isl_dim_out
, 1);
917 data
.sum
= isl_pw_qpolynomial_zero(isl_space_copy(data
.space
));
919 ctx
= isl_pw_qpolynomial_get_ctx(pwqp
);
920 data
.options
= isl_ctx_peek_barvinok_options(ctx
);
922 data
.options
= barvinok_options_new_with_defaults();
923 options_allocated
= 1;
926 if (isl_pw_qpolynomial_foreach_lifted_piece(pwqp
,
927 add_guarded_qp
, &data
) < 0)
930 if (options_allocated
)
931 barvinok_options_free(data
.options
);
933 isl_space_free(data
.space
);
935 isl_pw_qpolynomial_free(pwqp
);
939 if (options_allocated
)
940 barvinok_options_free(data
.options
);
941 isl_pw_qpolynomial_free(pwqp
);
942 isl_space_free(data
.space
);
943 isl_pw_qpolynomial_free(data
.sum
);
947 static isl_stat
pw_qpolynomial_sum(__isl_take isl_pw_qpolynomial
*pwqp
,
950 isl_union_pw_qpolynomial
**res
= (isl_union_pw_qpolynomial
**)user
;
951 isl_pw_qpolynomial
*sum
;
952 isl_union_pw_qpolynomial
*upwqp
;
954 sum
= isl_pw_qpolynomial_sum(pwqp
);
955 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(sum
);
956 *res
= isl_union_pw_qpolynomial_add(*res
, upwqp
);
961 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_sum(
962 __isl_take isl_union_pw_qpolynomial
*upwqp
)
965 isl_union_pw_qpolynomial
*res
;
967 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
968 res
= isl_union_pw_qpolynomial_zero(space
);
969 if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp
,
970 &pw_qpolynomial_sum
, &res
) < 0)
972 isl_union_pw_qpolynomial_free(upwqp
);
976 isl_union_pw_qpolynomial_free(upwqp
);
977 isl_union_pw_qpolynomial_free(res
);
981 static int join_compatible(__isl_keep isl_space
*space1
,
982 __isl_keep isl_space
*space2
)
985 m
= isl_space_has_equal_params(space1
, space2
);
988 return isl_space_tuple_is_equal(space1
, isl_dim_out
,
992 /* Compute the intersection of the range of the map and the domain
993 * of the piecewise quasipolynomial and then sum the associated
994 * quasipolynomial over all elements in this intersection.
996 * We first introduce some unconstrained dimensions in the
997 * piecewise quasipolynomial, intersect the resulting domain
998 * with the wrapped map and then compute the sum.
1000 __isl_give isl_pw_qpolynomial
*isl_map_apply_pw_qpolynomial(
1001 __isl_take isl_map
*map
, __isl_take isl_pw_qpolynomial
*pwqp
)
1005 isl_space
*map_space
;
1006 isl_space
*pwqp_space
;
1010 ctx
= isl_map_get_ctx(map
);
1014 map_space
= isl_map_get_space(map
);
1015 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1016 ok
= join_compatible(map_space
, pwqp_space
);
1017 isl_space_free(map_space
);
1018 isl_space_free(pwqp_space
);
1020 isl_die(ctx
, isl_error_invalid
, "incompatible dimensions",
1023 n_in
= isl_map_dim(map
, isl_dim_in
);
1024 pwqp
= isl_pw_qpolynomial_insert_dims(pwqp
, isl_dim_in
, 0, n_in
);
1026 dom
= isl_map_wrap(map
);
1027 pwqp
= isl_pw_qpolynomial_reset_domain_space(pwqp
,
1028 isl_set_get_space(dom
));
1030 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, dom
);
1031 pwqp
= isl_pw_qpolynomial_sum(pwqp
);
1036 isl_pw_qpolynomial_free(pwqp
);
1040 __isl_give isl_pw_qpolynomial
*isl_set_apply_pw_qpolynomial(
1041 __isl_take isl_set
*set
, __isl_take isl_pw_qpolynomial
*pwqp
)
1045 map
= isl_map_from_range(set
);
1046 pwqp
= isl_map_apply_pw_qpolynomial(map
, pwqp
);
1047 pwqp
= isl_pw_qpolynomial_project_domain_on_params(pwqp
);
1051 struct barvinok_apply_data
{
1052 isl_union_pw_qpolynomial
*upwqp
;
1053 isl_union_pw_qpolynomial
*res
;
1057 static isl_stat
pw_qpolynomial_apply(__isl_take isl_pw_qpolynomial
*pwqp
,
1060 isl_space
*map_space
;
1061 isl_space
*pwqp_space
;
1062 struct barvinok_apply_data
*data
= user
;
1065 map_space
= isl_map_get_space(data
->map
);
1066 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1067 ok
= join_compatible(map_space
, pwqp_space
);
1068 isl_space_free(map_space
);
1069 isl_space_free(pwqp_space
);
1072 isl_union_pw_qpolynomial
*upwqp
;
1074 pwqp
= isl_map_apply_pw_qpolynomial(isl_map_copy(data
->map
),
1076 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(pwqp
);
1077 data
->res
= isl_union_pw_qpolynomial_add(data
->res
, upwqp
);
1079 isl_pw_qpolynomial_free(pwqp
);
1084 static isl_stat
map_apply(__isl_take isl_map
*map
, void *user
)
1086 struct barvinok_apply_data
*data
= user
;
1090 r
= isl_union_pw_qpolynomial_foreach_pw_qpolynomial(data
->upwqp
,
1091 &pw_qpolynomial_apply
, data
);
1097 __isl_give isl_union_pw_qpolynomial
*isl_union_map_apply_union_pw_qpolynomial(
1098 __isl_take isl_union_map
*umap
,
1099 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1102 struct barvinok_apply_data data
;
1104 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1105 isl_union_map_get_space(umap
));
1106 umap
= isl_union_map_align_params(umap
,
1107 isl_union_pw_qpolynomial_get_space(upwqp
));
1110 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
1111 data
.res
= isl_union_pw_qpolynomial_zero(space
);
1112 if (isl_union_map_foreach_map(umap
, &map_apply
, &data
) < 0)
1115 isl_union_map_free(umap
);
1116 isl_union_pw_qpolynomial_free(upwqp
);
1120 isl_union_map_free(umap
);
1121 isl_union_pw_qpolynomial_free(upwqp
);
1122 isl_union_pw_qpolynomial_free(data
.res
);
1126 struct barvinok_apply_set_data
{
1127 isl_union_pw_qpolynomial
*upwqp
;
1128 isl_union_pw_qpolynomial
*res
;
1132 static isl_stat
pw_qpolynomial_apply_set(__isl_take isl_pw_qpolynomial
*pwqp
,
1135 isl_space
*set_space
;
1136 isl_space
*pwqp_space
;
1137 struct barvinok_apply_set_data
*data
= user
;
1140 set_space
= isl_set_get_space(data
->set
);
1141 pwqp_space
= isl_pw_qpolynomial_get_space(pwqp
);
1142 ok
= join_compatible(set_space
, pwqp_space
);
1143 isl_space_free(set_space
);
1144 isl_space_free(pwqp_space
);
1147 isl_union_pw_qpolynomial
*upwqp
;
1149 pwqp
= isl_set_apply_pw_qpolynomial(isl_set_copy(data
->set
),
1151 upwqp
= isl_union_pw_qpolynomial_from_pw_qpolynomial(pwqp
);
1152 data
->res
= isl_union_pw_qpolynomial_add(data
->res
, upwqp
);
1154 isl_pw_qpolynomial_free(pwqp
);
1159 static isl_stat
set_apply(__isl_take isl_set
*set
, void *user
)
1161 struct barvinok_apply_set_data
*data
= user
;
1165 r
= isl_union_pw_qpolynomial_foreach_pw_qpolynomial(data
->upwqp
,
1166 &pw_qpolynomial_apply_set
, data
);
1172 __isl_give isl_union_pw_qpolynomial
*isl_union_set_apply_union_pw_qpolynomial(
1173 __isl_take isl_union_set
*uset
,
1174 __isl_take isl_union_pw_qpolynomial
*upwqp
)
1177 struct barvinok_apply_set_data data
;
1179 upwqp
= isl_union_pw_qpolynomial_align_params(upwqp
,
1180 isl_union_set_get_space(uset
));
1181 uset
= isl_union_set_align_params(uset
,
1182 isl_union_pw_qpolynomial_get_space(upwqp
));
1185 space
= isl_union_pw_qpolynomial_get_space(upwqp
);
1186 data
.res
= isl_union_pw_qpolynomial_zero(space
);
1187 if (isl_union_set_foreach_set(uset
, &set_apply
, &data
) < 0)
1190 isl_union_set_free(uset
);
1191 isl_union_pw_qpolynomial_free(upwqp
);
1195 isl_union_set_free(uset
);
1196 isl_union_pw_qpolynomial_free(upwqp
);
1197 isl_union_pw_qpolynomial_free(data
.res
);
1201 evalue
*evalue_sum(evalue
*E
, int nvar
, unsigned MaxRays
)
1204 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1205 options
->MaxRays
= MaxRays
;
1206 sum
= barvinok_summate(E
, nvar
, options
);
1207 barvinok_options_free(options
);
1211 evalue
*esum(evalue
*e
, int nvar
)
1214 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
1215 sum
= barvinok_summate(e
, nvar
, options
);
1216 barvinok_options_free(options
);
1220 /* Turn unweighted counting problem into "weighted" counting problem
1221 * with weight equal to 1 and call barvinok_summate on this weighted problem.
1223 evalue
*barvinok_summate_unweighted(Polyhedron
*P
, Polyhedron
*C
,
1224 struct barvinok_options
*options
)
1230 if (emptyQ(P
) || emptyQ(C
))
1231 return evalue_zero();
1233 CA
= align_context(C
, P
->Dimension
, options
->MaxRays
);
1234 D
= DomainIntersection(P
, CA
, options
->MaxRays
);
1239 return evalue_zero();
1243 e
.x
.p
= new_enode(partition
, 2, P
->Dimension
);
1244 EVALUE_SET_DOMAIN(e
.x
.p
->arr
[0], D
);
1245 evalue_set_si(&e
.x
.p
->arr
[1], 1, 1);
1246 sum
= barvinok_summate(&e
, P
->Dimension
- C
->Dimension
, options
);
1247 free_evalue_refs(&e
);