1 #include <barvinok/options.h>
6 #include "section_array.h"
8 #define ALLOC(type) (type*)malloc(sizeof(type))
9 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
11 static evalue
*sum_over_polytope_with_equalities(Polyhedron
*P
, evalue
*E
,
13 struct evalue_section_array
*sections
,
14 struct barvinok_options
*options
)
16 unsigned dim
= P
->Dimension
;
17 unsigned new_dim
, new_nparam
;
18 Matrix
*T
= NULL
, *CP
= NULL
;
28 remove_all_equalities(&P
, NULL
, &CP
, &T
, dim
-nvar
, options
->MaxRays
);
35 new_nparam
= CP
? CP
->NbColumns
-1 : dim
- nvar
;
36 new_dim
= T
? T
->NbColumns
-1 : nvar
+ new_nparam
;
38 /* We can avoid these substitutions if E is a constant */
39 subs
= ALLOCN(evalue
*, dim
);
40 for (j
= 0; j
< nvar
; ++j
) {
42 subs
[j
] = affine2evalue(T
->p
[j
], T
->p
[nvar
+new_nparam
][new_dim
],
45 subs
[j
] = evalue_var(j
);
47 for (j
= 0; j
< dim
-nvar
; ++j
) {
49 subs
[nvar
+j
] = affine2evalue(CP
->p
[j
], CP
->p
[dim
-nvar
][new_nparam
],
52 subs
[nvar
+j
] = evalue_var(j
);
53 evalue_shift_variables(subs
[nvar
+j
], 0, new_dim
-new_nparam
);
57 evalue_substitute(E
, subs
);
60 for (j
= 0; j
< dim
; ++j
)
64 if (new_dim
-new_nparam
> 0) {
65 sum
= barvinok_sum_over_polytope(P
, E
, new_dim
-new_nparam
,
72 sum
->x
.p
= new_enode(partition
, 2, new_dim
);
73 EVALUE_SET_DOMAIN(sum
->x
.p
->arr
[0], P
);
74 value_clear(sum
->x
.p
->arr
[1].d
);
75 sum
->x
.p
->arr
[1] = *E
;
80 evalue_backsubstitute(sum
, CP
, options
->MaxRays
);
90 evalue
*barvinok_sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
91 struct evalue_section_array
*sections
,
92 struct barvinok_options
*options
)
95 return sum_over_polytope_with_equalities(P
, E
, nvar
, sections
, options
);
97 if (options
->summation
== BV_SUM_EULER
)
98 return euler_summate(P
, E
, nvar
, options
);
99 else if (options
->summation
== BV_SUM_LAURENT
)
100 return laurent_summate(P
, E
, nvar
, options
);
101 else if (options
->summation
== BV_SUM_BERNOULLI
)
102 return bernoulli_summate(P
, E
, nvar
, sections
, options
);
104 return box_summate(P
, E
, nvar
, options
->MaxRays
);
107 evalue
*barvinok_summate(evalue
*e
, int nvar
, struct barvinok_options
*options
)
110 struct evalue_section_array sections
;
114 if (nvar
== 0 || EVALUE_IS_ZERO(*e
))
115 return evalue_dup(e
);
117 assert(value_zero_p(e
->d
));
118 assert(e
->x
.p
->type
== partition
);
120 evalue_section_array_init(§ions
);
123 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
125 for (D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]); D
; D
= D
->next
) {
126 Polyhedron
*next
= D
->next
;
130 tmp
= barvinok_sum_over_polytope(D
, &e
->x
.p
->arr
[2*i
+1], nvar
,
146 evalue
*evalue_sum(evalue
*E
, int nvar
, unsigned MaxRays
)
149 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
150 options
->MaxRays
= MaxRays
;
151 sum
= barvinok_summate(E
, nvar
, options
);
152 barvinok_options_free(options
);
156 evalue
*esum(evalue
*e
, int nvar
)
159 struct barvinok_options
*options
= barvinok_options_new_with_defaults();
160 sum
= barvinok_summate(e
, nvar
, options
);
161 barvinok_options_free(options
);
165 /* Turn unweighted counting problem into "weighted" counting problem
166 * with weight equal to 1 and call barvinok_summate on this weighted problem.
168 evalue
*barvinok_summate_unweighted(Polyhedron
*P
, Polyhedron
*C
,
169 struct barvinok_options
*options
)
175 if (emptyQ(P
) || emptyQ(C
))
176 return evalue_zero();
178 CA
= align_context(C
, P
->Dimension
, options
->MaxRays
);
179 D
= DomainIntersection(P
, CA
, options
->MaxRays
);
184 return evalue_zero();
188 e
.x
.p
= new_enode(partition
, 2, P
->Dimension
);
189 EVALUE_SET_DOMAIN(e
.x
.p
->arr
[0], D
);
190 evalue_set_si(&e
.x
.p
->arr
[1], 1, 1);
191 sum
= barvinok_summate(&e
, P
->Dimension
- C
->Dimension
, options
);
192 free_evalue_refs(&e
);