2 #include <barvinok/options.h>
3 #include <barvinok/util.h>
5 #include "lattice_point.h"
7 #define ALLOC(type) (type*)malloc(sizeof(type))
8 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
9 #define REALLOCN(ptr,type,n) (type*)realloc(ptr, (n) * sizeof(type))
11 static struct bernoulli_coef bernoulli_coef
;
12 static struct poly_list bernoulli
;
13 static struct poly_list faulhaber
;
15 struct bernoulli_coef
*bernoulli_coef_compute(int n
)
20 if (n
< bernoulli_coef
.n
)
21 return &bernoulli_coef
;
23 if (n
>= bernoulli_coef
.size
) {
24 int size
= 3*(n
+ 5)/2;
27 b
= Vector_Alloc(size
);
28 if (bernoulli_coef
.n
) {
29 Vector_Copy(bernoulli_coef
.num
->p
, b
->p
, bernoulli_coef
.n
);
30 Vector_Free(bernoulli_coef
.num
);
32 bernoulli_coef
.num
= b
;
33 b
= Vector_Alloc(size
);
34 if (bernoulli_coef
.n
) {
35 Vector_Copy(bernoulli_coef
.den
->p
, b
->p
, bernoulli_coef
.n
);
36 Vector_Free(bernoulli_coef
.den
);
38 bernoulli_coef
.den
= b
;
39 b
= Vector_Alloc(size
);
40 if (bernoulli_coef
.n
) {
41 Vector_Copy(bernoulli_coef
.lcm
->p
, b
->p
, bernoulli_coef
.n
);
42 Vector_Free(bernoulli_coef
.lcm
);
44 bernoulli_coef
.lcm
= b
;
46 bernoulli_coef
.size
= size
;
50 for (i
= bernoulli_coef
.n
; i
<= n
; ++i
) {
52 value_set_si(bernoulli_coef
.num
->p
[0], 1);
53 value_set_si(bernoulli_coef
.den
->p
[0], 1);
54 value_set_si(bernoulli_coef
.lcm
->p
[0], 1);
57 value_set_si(bernoulli_coef
.num
->p
[i
], 0);
58 value_set_si(factor
, -(i
+1));
59 for (j
= i
-1; j
>= 0; --j
) {
60 mpz_mul_ui(factor
, factor
, j
+1);
61 mpz_divexact_ui(factor
, factor
, i
+1-j
);
62 value_division(tmp
, bernoulli_coef
.lcm
->p
[i
-1],
63 bernoulli_coef
.den
->p
[j
]);
64 value_multiply(tmp
, tmp
, bernoulli_coef
.num
->p
[j
]);
65 value_multiply(tmp
, tmp
, factor
);
66 value_addto(bernoulli_coef
.num
->p
[i
], bernoulli_coef
.num
->p
[i
], tmp
);
68 mpz_mul_ui(bernoulli_coef
.den
->p
[i
], bernoulli_coef
.lcm
->p
[i
-1], i
+1);
69 value_gcd(tmp
, bernoulli_coef
.num
->p
[i
], bernoulli_coef
.den
->p
[i
]);
70 if (value_notone_p(tmp
)) {
71 value_division(bernoulli_coef
.num
->p
[i
],
72 bernoulli_coef
.num
->p
[i
], tmp
);
73 value_division(bernoulli_coef
.den
->p
[i
],
74 bernoulli_coef
.den
->p
[i
], tmp
);
76 value_lcm(bernoulli_coef
.lcm
->p
[i
],
77 bernoulli_coef
.lcm
->p
[i
-1], bernoulli_coef
.den
->p
[i
]);
79 bernoulli_coef
.n
= n
+1;
83 return &bernoulli_coef
;
87 * Compute either Bernoulli B_n or Faulhaber F_n polynomials.
89 * B_n = sum_{k=0}^n { n \choose k } b_k x^{n-k}
90 * F_n = 1/(n+1) sum_{k=0}^n { n+1 \choose k } b_k x^{n+1-k}
92 static struct poly_list
*bernoulli_faulhaber_compute(int n
, struct poly_list
*pl
,
97 struct bernoulli_coef
*bc
;
103 int size
= 3*(n
+ 5)/2;
106 poly
= ALLOCN(Vector
*, size
);
107 for (i
= 0; i
< pl
->n
; ++i
)
108 poly
[i
] = pl
->poly
[i
];
115 bc
= bernoulli_coef_compute(n
);
118 for (i
= pl
->n
; i
<= n
; ++i
) {
119 pl
->poly
[i
] = Vector_Alloc(i
+faulhaber
+2);
120 value_assign(pl
->poly
[i
]->p
[i
+faulhaber
], bc
->lcm
->p
[i
]);
122 mpz_mul_ui(pl
->poly
[i
]->p
[i
+2], bc
->lcm
->p
[i
], i
+1);
124 value_assign(pl
->poly
[i
]->p
[i
+1], bc
->lcm
->p
[i
]);
125 value_set_si(factor
, 1);
126 for (j
= 1; j
<= i
; ++j
) {
127 mpz_mul_ui(factor
, factor
, i
+faulhaber
+1-j
);
128 mpz_divexact_ui(factor
, factor
, j
);
129 value_division(pl
->poly
[i
]->p
[i
+faulhaber
-j
],
130 bc
->lcm
->p
[i
], bc
->den
->p
[j
]);
131 value_multiply(pl
->poly
[i
]->p
[i
+faulhaber
-j
],
132 pl
->poly
[i
]->p
[i
+faulhaber
-j
], bc
->num
->p
[j
]);
133 value_multiply(pl
->poly
[i
]->p
[i
+faulhaber
-j
],
134 pl
->poly
[i
]->p
[i
+faulhaber
-j
], factor
);
136 Vector_Normalize(pl
->poly
[i
]->p
, i
+faulhaber
+2);
144 struct poly_list
*bernoulli_compute(int n
)
146 return bernoulli_faulhaber_compute(n
, &bernoulli
, 0);
149 struct poly_list
*faulhaber_compute(int n
)
151 return bernoulli_faulhaber_compute(n
, &faulhaber
, 1);
154 /* shift variables in polynomial one down */
155 static void shift(evalue
*e
)
158 if (value_notzero_p(e
->d
))
160 assert(e
->x
.p
->type
== polynomial
|| e
->x
.p
->type
== fractional
);
161 if (e
->x
.p
->type
== polynomial
) {
162 assert(e
->x
.p
->pos
> 1);
165 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
166 shift(&e
->x
.p
->arr
[i
]);
169 /* shift variables in polynomial n up */
170 static void unshift(evalue
*e
, unsigned n
)
173 if (value_notzero_p(e
->d
))
175 assert(e
->x
.p
->type
== polynomial
|| e
->x
.p
->type
== fractional
);
176 if (e
->x
.p
->type
== polynomial
)
178 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
179 unshift(&e
->x
.p
->arr
[i
], n
);
182 static evalue
*shifted_copy(const evalue
*src
)
184 evalue
*e
= ALLOC(evalue
);
191 /* Computes the argument for the Faulhaber polynomial.
192 * If we are computing a polynomial approximation (exact == 0),
193 * then this is simply arg/denom.
194 * Otherwise, if neg == 0, then we are dealing with an upper bound
195 * and we need to compute floor(arg/denom) = arg/denom - { arg/denom }
196 * If neg == 1, then we are dealing with a lower bound
197 * and we need to compute ceil(arg/denom) = arg/denom + { -arg/denom }
199 * Modifies arg (if exact == 1).
201 static evalue
*power_sums_base(Vector
*arg
, Value denom
, int neg
, int exact
)
204 evalue
*base
= affine2evalue(arg
->p
, denom
, arg
->Size
-1);
206 if (!exact
|| value_one_p(denom
))
210 Vector_Oppose(arg
->p
, arg
->p
, arg
->Size
);
212 fract
= fractional_part(arg
->p
, denom
, arg
->Size
-1, NULL
);
214 value_set_si(arg
->p
[0], -1);
215 evalue_mul(fract
, arg
->p
[0]);
223 static evalue
*power_sums(struct poly_list
*faulhaber
, const evalue
*poly
,
224 Vector
*arg
, Value denom
, int neg
, int alt_neg
,
228 evalue
*base
= power_sums_base(arg
, denom
, neg
, exact
);
229 evalue
*sum
= evalue_zero();
231 for (i
= 1; i
< poly
->x
.p
->size
; ++i
) {
232 evalue
*term
= evalue_polynomial(faulhaber
->poly
[i
], base
);
233 evalue
*factor
= shifted_copy(&poly
->x
.p
->arr
[i
]);
235 if (alt_neg
&& (i
% 2))
248 /* Given a constraint (cst_affine) a x + b y + c >= 0, compate a constraint (c)
249 * +- (b y + c) +- a >=,> 0
252 * sign_affine sign_cst
254 static void bound_constraint(Value
*c
, unsigned dim
,
256 int sign_affine
, int sign_cst
, int strict
)
258 if (sign_affine
== -1)
259 Vector_Oppose(cst_affine
+1, c
, dim
+1);
261 Vector_Copy(cst_affine
+1, c
, dim
+1);
264 value_subtract(c
[dim
], c
[dim
], cst_affine
[0]);
265 else if (sign_cst
== 1)
266 value_addto(c
[dim
], c
[dim
], cst_affine
[0]);
269 value_decrement(c
[dim
], c
[dim
]);
272 struct Bernoulli_data
{
273 struct barvinok_options
*options
;
274 struct evalue_section
*s
;
280 static evalue
*compute_poly_u(evalue
*poly_u
, Value
*upper
, Vector
*row
,
281 unsigned dim
, Value tmp
,
282 struct poly_list
*faulhaber
,
283 struct Bernoulli_data
*data
)
285 int exact
= data
->options
->approximation_method
== BV_APPROX_NONE
;
288 Vector_Copy(upper
+2, row
->p
, dim
+1);
289 value_oppose(tmp
, upper
[1]);
290 value_addto(row
->p
[dim
], row
->p
[dim
], tmp
);
291 return power_sums(faulhaber
, data
->e
, row
, tmp
, 0, 0, exact
);
294 static evalue
*compute_poly_l(evalue
*poly_l
, Value
*lower
, Vector
*row
,
296 struct poly_list
*faulhaber
,
297 struct Bernoulli_data
*data
)
299 int exact
= data
->options
->approximation_method
== BV_APPROX_NONE
;
302 Vector_Copy(lower
+2, row
->p
, dim
+1);
303 value_addto(row
->p
[dim
], row
->p
[dim
], lower
[1]);
304 return power_sums(faulhaber
, data
->e
, row
, lower
[1], 0, 1, exact
);
307 /* Compute sum of constant term.
309 static evalue
*linear_term(const evalue
*cst
, Value
*lower
, Value
*upper
,
310 Vector
*row
, Value tmp
, int exact
)
313 unsigned dim
= row
->Size
- 1;
315 if (EVALUE_IS_ZERO(*cst
))
316 return evalue_zero();
319 value_absolute(tmp
, upper
[1]);
321 Vector_Combine(lower
+2, upper
+2, row
->p
, tmp
, lower
[1], dim
+1);
322 value_multiply(tmp
, tmp
, lower
[1]);
323 /* upper - lower + 1 */
324 value_addto(row
->p
[dim
], row
->p
[dim
], tmp
);
326 linear
= affine2evalue(row
->p
, tmp
, dim
);
330 value_absolute(tmp
, upper
[1]);
331 Vector_Copy(upper
+2, row
->p
, dim
+1);
332 value_addto(row
->p
[dim
], row
->p
[dim
], tmp
);
334 linear
= power_sums_base(row
, tmp
, 0, 1);
336 Vector_Copy(lower
+2, row
->p
, dim
+1);
338 l
= power_sums_base(row
, lower
[1], 0, 1);
340 /* floor(upper+1) + floor(-lower) = floor(upper) - ceil(lower) + 1 */
349 static void Bernoulli_init(unsigned n
, void *cb_data
)
351 struct Bernoulli_data
*data
= (struct Bernoulli_data
*)cb_data
;
352 int exact
= data
->options
->approximation_method
== BV_APPROX_NONE
;
353 int cases
= exact
? 3 : 5;
355 if (cases
* n
<= data
->size
)
358 data
->size
= cases
* (n
+ 16);
359 data
->s
= REALLOCN(data
->s
, struct evalue_section
, data
->size
);
362 static void Bernoulli_cb(Matrix
*M
, Value
*lower
, Value
*upper
, void *cb_data
)
364 struct Bernoulli_data
*data
= (struct Bernoulli_data
*)cb_data
;
367 const evalue
*factor
= NULL
;
368 evalue
*linear
= NULL
;
371 unsigned dim
= M
->NbColumns
-2;
373 int exact
= data
->options
->approximation_method
== BV_APPROX_NONE
;
374 int cases
= exact
? 3 : 5;
378 assert(data
->ns
+ cases
<= data
->size
);
381 T
= Constraints2Polyhedron(M2
, data
->options
->MaxRays
);
384 POL_ENSURE_VERTICES(T
);
390 assert(lower
!= upper
);
392 row
= Vector_Alloc(dim
+1);
394 if (value_notzero_p(data
->e
->d
)) {
398 if (data
->e
->x
.p
->type
== polynomial
&& data
->e
->x
.p
->pos
== 1)
399 factor
= shifted_copy(&data
->e
->x
.p
->arr
[0]);
401 factor
= shifted_copy(data
->e
);
405 linear
= linear_term(factor
, lower
, upper
, row
, tmp
, exact
);
408 data
->s
[data
->ns
].E
= linear
;
409 data
->s
[data
->ns
].D
= T
;
411 data
->options
->stats
->bernoulli_sums
++;
413 evalue
*poly_u
= NULL
, *poly_l
= NULL
;
415 struct poly_list
*faulhaber
;
416 assert(data
->e
->x
.p
->type
== polynomial
);
417 assert(data
->e
->x
.p
->pos
== 1);
418 faulhaber
= faulhaber_compute(data
->e
->x
.p
->size
-1);
419 /* lower is the constraint
420 * b i - l' >= 0 i >= l'/b = l
421 * upper is the constraint
422 * -a i + u' >= 0 i <= u'/a = u
424 M2
= Matrix_Alloc(3, 2+T
->Dimension
);
425 value_set_si(M2
->p
[0][0], 1);
426 value_set_si(M2
->p
[1][0], 1);
427 value_set_si(M2
->p
[2][0], 1);
430 * 0 < l l' - 1 >= 0 if exact
433 bound_constraint(M2
->p
[0]+1, T
->Dimension
, lower
+1, -1, 0, 1);
435 bound_constraint(M2
->p
[0]+1, T
->Dimension
, lower
+1, -1, -1, 0);
436 D
= AddConstraints(M2
->p_Init
, 1, T
, data
->options
->MaxRays
);
437 POL_ENSURE_VERTICES(D
);
442 poly_u
= compute_poly_u(poly_u
, upper
, row
, dim
, tmp
,
444 Vector_Oppose(lower
+2, row
->p
, dim
+1);
445 extra
= power_sums(faulhaber
, data
->e
, row
, lower
[1], 1, 0, exact
);
449 data
->s
[data
->ns
].E
= extra
;
450 data
->s
[data
->ns
].D
= D
;
452 data
->options
->stats
->bernoulli_sums
++;
456 * 1 <= -u -u' - a >= 0
457 * 0 < -u -u' - 1 >= 0 if exact
460 bound_constraint(M2
->p
[0]+1, T
->Dimension
, upper
+1, -1, 0, 1);
462 bound_constraint(M2
->p
[0]+1, T
->Dimension
, upper
+1, -1, 1, 0);
463 D
= AddConstraints(M2
->p_Init
, 1, T
, data
->options
->MaxRays
);
464 POL_ENSURE_VERTICES(D
);
469 poly_l
= compute_poly_l(poly_l
, lower
, row
, dim
, faulhaber
, data
);
470 Vector_Oppose(upper
+2, row
->p
, dim
+1);
471 value_oppose(tmp
, upper
[1]);
472 extra
= power_sums(faulhaber
, data
->e
, row
, tmp
, 1, 1, exact
);
476 data
->s
[data
->ns
].E
= extra
;
477 data
->s
[data
->ns
].D
= D
;
479 data
->options
->stats
->bernoulli_sums
++;
486 bound_constraint(M2
->p
[0]+1, T
->Dimension
, upper
+1, 1, 0, 0);
487 bound_constraint(M2
->p
[1]+1, T
->Dimension
, lower
+1, 1, 0, 0);
488 D
= AddConstraints(M2
->p_Init
, 2, T
, data
->options
->MaxRays
);
489 POL_ENSURE_VERTICES(D
);
493 poly_l
= compute_poly_l(poly_l
, lower
, row
, dim
, faulhaber
, data
);
494 poly_u
= compute_poly_u(poly_u
, upper
, row
, dim
, tmp
,
497 data
->s
[data
->ns
].E
= ALLOC(evalue
);
498 value_init(data
->s
[data
->ns
].E
->d
);
499 evalue_copy(data
->s
[data
->ns
].E
, poly_u
);
500 eadd(poly_l
, data
->s
[data
->ns
].E
);
501 eadd(linear
, data
->s
[data
->ns
].E
);
502 data
->s
[data
->ns
].D
= D
;
504 data
->options
->stats
->bernoulli_sums
++;
509 * l < 1 -l' + b - 1 >= 0
513 bound_constraint(M2
->p
[0]+1, T
->Dimension
, lower
+1, 1, 1, 1);
514 bound_constraint(M2
->p
[1]+1, T
->Dimension
, lower
+1, -1, 0, 1);
515 bound_constraint(M2
->p
[2]+1, T
->Dimension
, upper
+1, 1, 1, 0);
516 D
= AddConstraints(M2
->p_Init
, 3, T
, data
->options
->MaxRays
);
517 POL_ENSURE_VERTICES(D
);
521 poly_u
= compute_poly_u(poly_u
, upper
, row
, dim
, tmp
,
523 eadd(linear
, poly_u
);
524 data
->s
[data
->ns
].E
= poly_u
;
526 data
->s
[data
->ns
].D
= D
;
528 data
->options
->stats
->bernoulli_sums
++;
532 * -u < 1 u' + a - 1 >= 0
533 * 0 < -u -u' - 1 >= 0
534 * l <= -1 -l' - b >= 0
536 bound_constraint(M2
->p
[0]+1, T
->Dimension
, upper
+1, 1, -1, 1);
537 bound_constraint(M2
->p
[1]+1, T
->Dimension
, upper
+1, -1, 0, 1);
538 bound_constraint(M2
->p
[2]+1, T
->Dimension
, lower
+1, 1, -1, 0);
539 D
= AddConstraints(M2
->p_Init
, 3, T
, data
->options
->MaxRays
);
540 POL_ENSURE_VERTICES(D
);
544 poly_l
= compute_poly_l(poly_l
, lower
, row
, dim
,
546 eadd(linear
, poly_l
);
547 data
->s
[data
->ns
].E
= poly_l
;
549 data
->s
[data
->ns
].D
= D
;
551 data
->options
->stats
->bernoulli_sums
++;
563 if (factor
!= data
->e
)
564 evalue_free((evalue
*)factor
);
570 * Move the variable at position pos to the front by exchanging
571 * that variable with the first variable.
573 static void more_var_to_front(Polyhedron
**P_p
, evalue
**E_p
, int pos
)
575 Polyhedron
*P
= *P_p
;
577 unsigned dim
= P
->Dimension
;
581 P
= Polyhedron_Copy(P
);
582 Polyhedron_ExchangeColumns(P
, 1, 1+pos
);
585 if (value_zero_p(E
->d
)) {
589 subs
= ALLOCN(evalue
*, dim
);
590 for (j
= 0; j
< dim
; ++j
)
591 subs
[j
] = evalue_var(j
);
595 E
= evalue_dup(*E_p
);
596 evalue_substitute(E
, subs
);
597 for (j
= 0; j
< dim
; ++j
)
598 evalue_free(subs
[j
]);
604 static int type_offset(enode
*p
)
606 return p
->type
== fractional
? 1 :
607 p
->type
== flooring
? 1 : 0;
610 static void adjust_periods(evalue
*e
, unsigned nvar
, Vector
*periods
)
612 for (; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
614 assert(e
->x
.p
->type
== polynomial
);
615 assert(e
->x
.p
->size
== 2);
616 assert(value_notzero_p(e
->x
.p
->arr
[1].d
));
618 pos
= e
->x
.p
->pos
- 1;
622 value_lcm(periods
->p
[pos
], periods
->p
[pos
], e
->x
.p
->arr
[1].d
);
626 static void fractional_periods_r(evalue
*e
, unsigned nvar
, Vector
*periods
)
630 if (value_notzero_p(e
->d
))
633 assert(e
->x
.p
->type
== polynomial
|| e
->x
.p
->type
== fractional
);
635 if (e
->x
.p
->type
== fractional
)
636 adjust_periods(&e
->x
.p
->arr
[0], nvar
, periods
);
638 for (i
= type_offset(e
->x
.p
); i
< e
->x
.p
->size
; ++i
)
639 fractional_periods_r(&e
->x
.p
->arr
[i
], nvar
, periods
);
643 * For each of the nvar variables, compute the lcm of the
644 * denominators of the coefficients of that variable in
645 * any of the fractional parts.
647 static Vector
*fractional_periods(evalue
*e
, unsigned nvar
)
650 Vector
*periods
= Vector_Alloc(nvar
);
652 for (i
= 0; i
< nvar
; ++i
)
653 value_set_si(periods
->p
[i
], 1);
655 fractional_periods_r(e
, nvar
, periods
);
660 /* Move "best" variable to sum over into the first position,
661 * possibly changing *P_p and *E_p.
663 * If there are any fractional parts (period != NULL), then we
664 * first look for a variable with the smallest lcm of denominators
665 * inside a fractional part. This denominator is assigned to period
666 * and corresponds to the number of "splinters" we need to construct
669 * Of those with this denominator (all if period == NULL or if there
670 * are no fractional parts), we select the variable with the smallest
671 * maximal coefficient, as this coefficient will become a denominator
672 * in new fractional parts (for an exact computation), which may
673 * lead to splintering in the next step.
675 static void move_best_to_front(Polyhedron
**P_p
, evalue
**E_p
, unsigned nvar
,
678 Polyhedron
*P
= *P_p
;
680 int i
, j
, best_i
= -1;
687 periods
= fractional_periods(E
, nvar
);
688 value_assign(*period
, periods
->p
[0]);
689 for (i
= 1; i
< nvar
; ++i
)
690 if (value_lt(periods
->p
[i
], *period
))
691 value_assign(*period
, periods
->p
[i
]);
697 for (i
= 0; i
< nvar
; ++i
) {
698 if (period
&& value_ne(*period
, periods
->p
[i
]))
701 value_set_si(max
, 0);
703 for (j
= 0; j
< P
->NbConstraints
; ++j
) {
704 if (value_zero_p(P
->Constraint
[j
][1+i
]))
706 if (First_Non_Zero(P
->Constraint
[j
]+1, i
) == -1 &&
707 First_Non_Zero(P
->Constraint
[j
]+1+i
+1, nvar
-i
-1) == -1)
709 if (value_abs_gt(P
->Constraint
[j
][1+i
], max
))
710 value_absolute(max
, P
->Constraint
[j
][1+i
]);
713 if (best_i
== -1 || value_lt(max
, best
)) {
714 value_assign(best
, max
);
723 Vector_Free(periods
);
726 more_var_to_front(P_p
, E_p
, best_i
);
731 static evalue
*sum_over_polytope_base(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
732 struct Bernoulli_data
*data
,
733 struct barvinok_options
*options
)
737 assert(P
->NbEq
== 0);
742 for_each_lower_upper_bound(P
, Bernoulli_init
, Bernoulli_cb
, data
);
744 res
= evalue_from_section_array(data
->s
, data
->ns
);
747 evalue
*tmp
= Bernoulli_sum_evalue(res
, nvar
-1, options
);
755 static evalue
*sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
756 struct Bernoulli_data
*data
,
757 struct barvinok_options
*options
);
759 static evalue
*sum_over_polytope_with_equalities(Polyhedron
*P
, evalue
*E
,
761 struct Bernoulli_data
*data
,
762 struct barvinok_options
*options
)
764 unsigned dim
= P
->Dimension
;
765 unsigned new_dim
, new_nparam
;
766 Matrix
*T
= NULL
, *CP
= NULL
;
772 return evalue_zero();
776 remove_all_equalities(&P
, NULL
, &CP
, &T
, dim
-nvar
, options
->MaxRays
);
780 return evalue_zero();
783 new_nparam
= CP
? CP
->NbColumns
-1 : dim
- nvar
;
784 new_dim
= T
? T
->NbColumns
-1 : nvar
+ new_nparam
;
786 /* We can avoid these substitutions if E is a constant */
787 subs
= ALLOCN(evalue
*, dim
);
788 for (j
= 0; j
< nvar
; ++j
) {
790 subs
[j
] = affine2evalue(T
->p
[j
], T
->p
[nvar
+new_nparam
][new_dim
],
793 subs
[j
] = evalue_var(j
);
795 for (j
= 0; j
< dim
-nvar
; ++j
) {
797 subs
[nvar
+j
] = affine2evalue(CP
->p
[j
], CP
->p
[dim
-nvar
][new_nparam
],
800 subs
[nvar
+j
] = evalue_var(j
);
801 unshift(subs
[nvar
+j
], new_dim
-new_nparam
);
805 evalue_substitute(E
, subs
);
808 for (j
= 0; j
< dim
; ++j
)
809 evalue_free(subs
[j
]);
812 if (new_dim
-new_nparam
> 0) {
813 sum
= sum_over_polytope(P
, E
, new_dim
-new_nparam
, data
, options
);
819 sum
->x
.p
= new_enode(partition
, 2, new_dim
);
820 EVALUE_SET_DOMAIN(sum
->x
.p
->arr
[0], P
);
821 value_clear(sum
->x
.p
->arr
[1].d
);
822 sum
->x
.p
->arr
[1] = *E
;
827 evalue_backsubstitute(sum
, CP
, options
->MaxRays
);
837 /* Splinter P into period slices along the first variable x = period y + c,
838 * 0 <= c < perdiod, * ensuring no fractional part contains the first variable,
839 * and sum over all slices.
841 static evalue
*sum_over_polytope_slices(Polyhedron
*P
, evalue
*E
,
844 struct Bernoulli_data
*data
,
845 struct barvinok_options
*options
)
847 evalue
*sum
= evalue_zero();
849 unsigned dim
= P
->Dimension
;
857 value_set_si(one
, 1);
859 subs
= ALLOCN(evalue
*, dim
);
861 T
= Matrix_Alloc(dim
+1, dim
+1);
862 value_assign(T
->p
[0][0], period
);
863 for (j
= 1; j
< dim
+1; ++j
)
864 value_set_si(T
->p
[j
][j
], 1);
866 for (j
= 0; j
< dim
; ++j
)
867 subs
[j
] = evalue_var(j
);
868 evalue_mul(subs
[0], period
);
870 for (value_set_si(i
, 0); value_lt(i
, period
); value_increment(i
, i
)) {
872 Polyhedron
*S
= DomainPreimage(P
, T
, options
->MaxRays
);
873 evalue
*e
= evalue_dup(E
);
874 evalue_substitute(e
, subs
);
878 tmp
= sum_over_polytope_with_equalities(S
, e
, nvar
, data
, options
);
880 tmp
= sum_over_polytope_base(S
, e
, nvar
, data
, options
);
889 value_increment(T
->p
[0][dim
], T
->p
[0][dim
]);
890 evalue_add_constant(subs
[0], one
);
896 for (j
= 0; j
< dim
; ++j
)
897 evalue_free(subs
[j
]);
904 static evalue
*sum_over_polytope(Polyhedron
*P
, evalue
*E
, unsigned nvar
,
905 struct Bernoulli_data
*data
,
906 struct barvinok_options
*options
)
908 Polyhedron
*P_orig
= P
;
912 int exact
= options
->approximation_method
== BV_APPROX_NONE
;
915 return sum_over_polytope_with_equalities(P
, E
, nvar
, data
, options
);
919 move_best_to_front(&P
, &E
, nvar
, exact
? &period
: NULL
);
920 if (exact
&& value_notone_p(period
))
921 sum
= sum_over_polytope_slices(P
, E
, nvar
, period
, data
, options
);
923 sum
= sum_over_polytope_base(P
, E
, nvar
, data
, options
);
935 evalue
*Bernoulli_sum_evalue(evalue
*e
, unsigned nvar
,
936 struct barvinok_options
*options
)
938 struct Bernoulli_data data
;
940 evalue
*sum
= evalue_zero();
942 if (EVALUE_IS_ZERO(*e
))
950 assert(value_zero_p(e
->d
));
951 assert(e
->x
.p
->type
== partition
);
954 data
.s
= ALLOCN(struct evalue_section
, data
.size
);
955 data
.options
= options
;
957 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
959 for (D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]); D
; D
= D
->next
) {
960 Polyhedron
*next
= D
->next
;
964 tmp
= sum_over_polytope(D
, &e
->x
.p
->arr
[2*i
+1], nvar
, &data
, options
);
979 evalue
*Bernoulli_sum(Polyhedron
*P
, Polyhedron
*C
,
980 struct barvinok_options
*options
)
986 if (emptyQ(P
) || emptyQ(C
))
987 return evalue_zero();
989 CA
= align_context(C
, P
->Dimension
, options
->MaxRays
);
990 D
= DomainIntersection(P
, CA
, options
->MaxRays
);
995 return evalue_zero();
999 e
.x
.p
= new_enode(partition
, 2, P
->Dimension
);
1000 EVALUE_SET_DOMAIN(e
.x
.p
->arr
[0], D
);
1001 evalue_set_si(&e
.x
.p
->arr
[1], 1, 1);
1002 sum
= Bernoulli_sum_evalue(&e
, P
->Dimension
- C
->Dimension
, options
);
1003 free_evalue_refs(&e
);