rename barvinok_maximize to barvinok_bound
[barvinok.git] / euler.cc
blobe25465ed589e1133b648d6fe83cbdd2a73eab955
1 /*
2 * Sum polynomial over integer points in polytope using local
3 * Euler-Maclaurin formula by Berline and Vergne.
4 */
6 #include <assert.h>
7 #include <barvinok/options.h>
8 #include <barvinok/util.h>
9 #include "bernoulli.h"
10 #include "conversion.h"
11 #include "decomposer.h"
12 #include "euler.h"
13 #include "lattice_point.h"
14 #include "param_util.h"
15 #include "reduce_domain.h"
17 /* Compute total degree in first nvar variables */
18 static unsigned total_degree(const evalue *e, unsigned nvar)
20 int i;
21 unsigned max_degree;
23 if (value_notzero_p(e->d))
24 return 0;
25 assert(e->x.p->type == polynomial);
26 if (e->x.p->pos-1 >= nvar)
27 return 0;
29 max_degree = total_degree(&e->x.p->arr[0], nvar);
30 for (i = 1; i < e->x.p->size; ++i) {
31 unsigned degree = i + total_degree(&e->x.p->arr[i], nvar);
32 if (degree > max_degree)
33 max_degree = degree;
35 return max_degree;
38 struct fact {
39 Value *fact;
40 unsigned size;
41 unsigned n;
43 struct fact fact;
45 Value *factorial(unsigned n)
47 if (n < fact.n)
48 return &fact.fact[n];
50 if (n >= fact.size) {
51 int size = 3*(n + 5)/2;
53 fact.fact = (Value *)realloc(fact.fact, size*sizeof(Value));
54 fact.size = size;
56 for (int i = fact.n; i <= n; ++i) {
57 value_init(fact.fact[i]);
58 if (!i)
59 value_set_si(fact.fact[0], 1);
60 else
61 mpz_mul_ui(fact.fact[i], fact.fact[i-1], i);
63 fact.n = n+1;
64 return &fact.fact[n];
67 struct binom {
68 Vector **binom;
69 unsigned size;
70 unsigned n;
72 struct binom binom;
74 Value *binomial(unsigned n, unsigned k)
76 if (n < binom.n)
77 return &binom.binom[n]->p[k];
79 if (n >= binom.size) {
80 int size = 3*(n + 5)/2;
82 binom.binom = (Vector **)realloc(binom.binom, size*sizeof(Vector *));
83 binom.size = size;
85 for (int i = binom.n; i <= n; ++i) {
86 binom.binom[i] = Vector_Alloc(i+1);
87 if (!i)
88 value_set_si(binom.binom[0]->p[0], 1);
89 else {
90 value_set_si(binom.binom[i]->p[0], 1);
91 value_set_si(binom.binom[i]->p[i], 1);
92 for (int j = 1; j < i; ++j)
93 value_addto(binom.binom[i]->p[j],
94 binom.binom[i-1]->p[j-1], binom.binom[i-1]->p[j]);
97 binom.n = n+1;
98 return &binom.binom[n]->p[k];
101 struct power {
102 int n;
103 Vector *powers;
105 power(Value v, int max) {
106 powers = Vector_Alloc(max+1);
107 assert(powers);
108 value_set_si(powers->p[0], 1);
109 if (max >= 1)
110 value_assign(powers->p[1], v);
111 n = 2;
113 ~power() {
114 Vector_Free(powers);
116 Value *operator[](int exp) {
117 assert(exp >= 0);
118 assert(exp < powers->Size);
119 for (; n <= exp; ++n)
120 value_multiply(powers->p[n], powers->p[n-1], powers->p[1]);
121 return &powers->p[exp];
126 * Computes the coefficients of
128 * \mu(-t + R_+)(\xi) = \sum_{n=0)^\infty -b(n+1, t)/(n+1)! \xi^n
130 * where b(n, t) is the Bernoulli polynomial of degree n in t
131 * and t(p) is an expression (a fractional part) of the parameters p
132 * such that 0 <= t(p) < 1 for all values of the parameters.
133 * The coefficients are computed on demand up to (and including)
134 * the maximal degree max_degree.
136 struct mu_1d {
137 unsigned max_degree;
138 evalue **coefficients;
139 const evalue *t;
141 mu_1d(unsigned max_degree, evalue *t) : max_degree(max_degree), t(t) {
142 coefficients = new evalue *[max_degree+1];
143 for (int i = 0; i < max_degree+1; ++i)
144 coefficients[i] = NULL;
146 ~mu_1d() {
147 for (int i = 0; i < max_degree+1; ++i)
148 if (coefficients[i])
149 evalue_free(coefficients[i]);
150 delete [] coefficients;
152 void compute_coefficient(unsigned n);
153 const evalue *coefficient(unsigned n) {
154 if (!coefficients[n])
155 compute_coefficient(n);
156 return coefficients[n];
160 void mu_1d::compute_coefficient(unsigned n)
162 struct poly_list *bernoulli = bernoulli_compute(n+1);
163 evalue *c = evalue_polynomial(bernoulli->poly[n+1], t);
164 evalue_negate(c);
165 evalue_div(c, *factorial(n+1));
167 coefficients[n] = c;
171 * Computes the coefficients of
173 * \mu(a)(y) = \sum_{n_1} \sum_{n_2} c_{n_1,n_2} y^{n_1} y^{n_2}
175 * with c_{n1,n2} given by
177 * b(n1+1,t1)/(n1+1)! b(n2+1,t2)/(n2+1)!
178 * - b(n1+n2+2,t2)/(n1+n2+2)! (-c1)^{n1+1}
179 * - b(n1+n2+2,t1)/(n1+n2+2)! (-c2)^{n2+1}
181 * where b(n, t) is the Bernoulli polynomial of degree n in t,
182 * t1(p) and t2(p) are expressions (fractional parts) of the parameters p
183 * such that 0 <= t1(p), t2(p) < 1 for all values of the parameters
184 * and c1 = cn/c1d and c2 = cn/c2d.
185 * The coefficients are computed on demand up to (and including)
186 * the maximal degree (n1,n2) = (max_degree,max_degree).
188 * bernoulli_t[i][j] contains b(j+1, t_i)/(j+1)!
190 struct mu_2d {
191 unsigned max_degree;
192 evalue ***coefficients;
193 /* bernoulli_t[i][n] stores b(n+1, t_i)/(n+1)! */
194 evalue **bernoulli_t[2];
195 /* stores the powers of -cn */
196 struct power *power_cn;
197 struct power *power_c1d;
198 struct power *power_c2d;
199 const evalue *t[2];
201 mu_2d(unsigned max_degree, evalue *t1, evalue *t2,
202 Value cn, Value c1d, Value c2d) : max_degree(max_degree) {
203 t[0] = t1;
204 t[1] = t2;
205 coefficients = new evalue **[max_degree+1];
206 for (int i = 0; i < max_degree+1; ++i) {
207 coefficients[i] = new evalue *[max_degree+1];
208 for (int j = 0; j < max_degree+1; ++j)
209 coefficients[i][j] = NULL;
211 for (int i = 0; i < 2; ++i) {
212 bernoulli_t[i] = new evalue *[max_degree+2];
213 for (int j = 0; j < max_degree+2; ++j)
214 bernoulli_t[i][j] = NULL;
216 value_oppose(cn, cn);
217 power_cn = new struct power(cn, max_degree+1);
218 value_oppose(cn, cn);
219 power_c1d = new struct power(c1d, max_degree+1);
220 power_c2d = new struct power(c2d, max_degree+1);
222 ~mu_2d() {
223 for (int i = 0; i < max_degree+1; ++i) {
224 for (int j = 0; j < max_degree+1; ++j)
225 if (coefficients[i][j])
226 evalue_free(coefficients[i][j]);
227 delete [] coefficients[i];
229 delete [] coefficients;
230 for (int i = 0; i < 2; ++i)
231 for (int j = 0; j < max_degree+2; ++j)
232 if (bernoulli_t[i][j])
233 evalue_free(bernoulli_t[i][j]);
234 for (int i = 0; i < 2; ++i)
235 delete [] bernoulli_t[i];
236 delete power_cn;
237 delete power_c1d;
238 delete power_c2d;
240 const evalue *get_bernoulli(int n, int i);
242 void compute_coefficient(unsigned n1, unsigned n2);
243 const evalue *coefficient(unsigned n1, unsigned n2) {
244 if (!coefficients[n1][n2])
245 compute_coefficient(n1, n2);
246 return coefficients[n1][n2];
251 * Returns b(n, t_i)/n!
253 const evalue *mu_2d::get_bernoulli(int n, int i)
255 if (!bernoulli_t[i][n-1]) {
256 struct poly_list *bernoulli = bernoulli_compute(n);
257 bernoulli_t[i][n-1] = evalue_polynomial(bernoulli->poly[n], t[i]);
258 evalue_div(bernoulli_t[i][n-1], *factorial(n));
260 return bernoulli_t[i][n-1];
263 void mu_2d::compute_coefficient(unsigned n1, unsigned n2)
265 evalue *c = evalue_dup(get_bernoulli(n1+1, 0));
266 emul(get_bernoulli(n2+1, 1), c);
268 if (value_notzero_p(*(*power_cn)[1])) {
269 evalue *t;
270 Value neg_power;
272 value_init(neg_power);
274 t = evalue_dup(get_bernoulli(n1+n2+2, 1));
275 value_multiply(neg_power,
276 *(*power_cn)[n1+1], *binomial(n1+n2+1, n1+1));
277 value_oppose(neg_power, neg_power);
278 evalue_mul_div(t, neg_power, *(*power_c1d)[n1+1]);
279 eadd(t, c);
280 evalue_free(t);
282 t = evalue_dup(get_bernoulli(n1+n2+2, 0));
283 value_multiply(neg_power,
284 *(*power_cn)[n2+1], *binomial(n1+n2+1, n2+1));
285 value_oppose(neg_power, neg_power);
286 evalue_mul_div(t, neg_power, *(*power_c2d)[n2+1]);
287 eadd(t, c);
288 evalue_free(t);
290 value_clear(neg_power);
293 coefficients[n1][n2] = c;
296 /* Later: avoid recomputation of mu of faces that appear in
297 * more than one domain.
299 struct summator_2d : public signed_cone_consumer, public vertex_decomposer {
300 const evalue *polynomial;
301 Value *inner;
302 unsigned nparam;
304 /* substitutions to use when result is 0-dimensional (only parameters) */
305 evalue **subs_0d;
306 /* substitutions to use when result is 1-dimensional */
307 evalue **subs_1d;
308 evalue *sum;
310 summator_2d(evalue *e, Param_Polyhedron *PP, Value *inner,
311 unsigned nparam) :
312 polynomial(e), vertex_decomposer(PP, *this),
313 inner(inner), nparam(nparam) {
314 sum = evalue_zero();
316 subs_0d = new evalue *[2+nparam];
317 subs_1d = new evalue *[2+nparam];
318 subs_0d[0] = NULL;
319 subs_0d[1] = NULL;
320 subs_1d[0] = NULL;
321 subs_1d[1] = NULL;
322 for (int i = 0; i < nparam; ++i) {
323 subs_0d[2+i] = evalue_var(i);
324 subs_1d[2+i] = evalue_var(1+i);
327 ~summator_2d() {
328 for (int i = 0; i < nparam; ++i) {
329 evalue_free(subs_0d[2+i]);
330 evalue_free(subs_1d[2+i]);
332 delete [] subs_0d;
333 delete [] subs_1d;
335 evalue *summate_over_pdomain(Param_Polyhedron *PP, unsigned *facets,
336 Param_Domain *PD,
337 struct barvinok_options *options);
338 void handle_facet(Param_Polyhedron *PP, Param_Domain *FD, Value *normal);
339 void integrate(Param_Polyhedron *PP, unsigned *facets, Param_Domain *PD);
340 virtual void handle(const signed_cone& sc, barvinok_options *options);
343 /* Replaces poly by its derivative along variable var */
344 static void evalue_derive(evalue *poly, int var)
346 if (value_notzero_p(poly->d)) {
347 value_set_si(poly->x.n, 0);
348 value_set_si(poly->d, 1);
349 return;
351 assert(poly->x.p->type == polynomial);
352 if (poly->x.p->pos-1 > var) {
353 free_evalue_refs(poly);
354 value_init(poly->d);
355 evalue_set_si(poly, 0, 1);
356 return;
359 if (poly->x.p->pos-1 < var) {
360 for (int i = 0; i < poly->x.p->size; ++i)
361 evalue_derive(&poly->x.p->arr[i], var);
362 reduce_evalue(poly);
363 return;
366 assert(poly->x.p->size > 1);
367 enode *p = poly->x.p;
368 free_evalue_refs(&p->arr[0]);
369 if (p->size == 2) {
370 value_clear(poly->d);
371 *poly = p->arr[1];
372 free(p);
373 return;
376 p->size--;
377 Value factor;
378 value_init(factor);
379 for (int i = 0; i < p->size; ++i) {
380 value_set_si(factor, i+1);
381 p->arr[i] = p->arr[i+1];
382 evalue_mul(&p->arr[i], factor);
384 value_clear(factor);
387 /* Check whether e is constant with respect to variable var */
388 static int evalue_is_constant(evalue *e, int var)
390 int i;
392 if (value_notzero_p(e->d))
393 return 1;
394 if (e->x.p->type == polynomial && e->x.p->pos-1 == var)
395 return 0;
396 assert(e->x.p->type == polynomial ||
397 e->x.p->type == fractional ||
398 e->x.p->type == flooring);
399 for (i = 0; i < e->x.p->size; ++i)
400 if (!evalue_is_constant(&e->x.p->arr[i], var))
401 return 0;
402 return 1;
405 /* Replaces poly by its anti-derivative with constant 0 along variable var */
406 static void evalue_anti_derive(evalue *poly, int var)
408 enode *p;
410 if (value_zero_p(poly->d) &&
411 poly->x.p->type == polynomial && poly->x.p->pos-1 < var) {
412 for (int i = 0; i < poly->x.p->size; ++i)
413 evalue_anti_derive(&poly->x.p->arr[i], var);
414 reduce_evalue(poly);
415 return;
418 if (evalue_is_constant(poly, var)) {
419 p = new_enode(polynomial, 2, 1+var);
420 evalue_set_si(&p->arr[0], 0, 1);
421 value_clear(p->arr[1].d);
422 p->arr[1] = *poly;
423 value_init(poly->d);
424 poly->x.p = p;
425 return;
427 assert(poly->x.p->type == polynomial);
429 p = new_enode(polynomial, poly->x.p->size+1, 1+var);
430 evalue_set_si(&p->arr[0], 0, 1);
431 for (int i = 0; i < poly->x.p->size; ++i) {
432 value_clear(p->arr[1+i].d);
433 p->arr[1+i] = poly->x.p->arr[i];
434 value_set_si(poly->d, 1+i);
435 evalue_div(&p->arr[1+i], poly->d);
437 free(poly->x.p);
438 poly->x.p = p;
439 value_set_si(poly->d, 0);
442 /* Computes offsets in the basis given by the rays of the cone
443 * to the integer point in the fundamental parallelepiped of
444 * the cone.
445 * The resulting evalues contain only the parameters as variables.
447 evalue **offsets_to_integer_point(Matrix *Rays, Matrix *vertex)
449 unsigned nparam = vertex->NbColumns-2;
450 evalue **t = new evalue *[2];
452 if (value_one_p(vertex->p[0][nparam+1])) {
453 t[0] = evalue_zero();
454 t[1] = evalue_zero();
455 } else {
456 Matrix *R2 = Matrix_Copy(Rays);
457 Matrix_Transposition(R2);
458 Matrix *inv = Matrix_Alloc(Rays->NbColumns, Rays->NbRows);
459 int ok = Matrix_Inverse(R2, inv);
460 assert(ok);
461 Matrix_Free(R2);
463 /* We want the fractional part of the negative relative coordinates */
464 Vector_Oppose(inv->p[0], inv->p[0], inv->NbColumns);
465 Vector_Oppose(inv->p[1], inv->p[1], inv->NbColumns);
467 Matrix *neg_rel = Matrix_Alloc(2, nparam+1);
468 vertex->NbColumns--;
469 Matrix_Product(inv, vertex, neg_rel);
470 Matrix_Free(inv);
471 vertex->NbColumns++;
472 t[0] = fractional_part(neg_rel->p[0], vertex->p[0][nparam+1],
473 nparam, NULL);
474 t[1] = fractional_part(neg_rel->p[1], vertex->p[0][nparam+1],
475 nparam, NULL);
476 Matrix_Free(neg_rel);
479 return t;
483 * Called from decompose_at_vertex.
485 * Handles a cone in the signed decomposition of the supporting
486 * cone of a vertex. The cone is assumed to be unimodular.
488 void summator_2d::handle(const signed_cone& sc, barvinok_options *options)
490 evalue **t;
491 unsigned degree = total_degree(polynomial, 2);
493 subs_0d[0] = affine2evalue(V->Vertex->p[0],
494 V->Vertex->p[0][nparam+1], nparam);
495 subs_0d[1] = affine2evalue(V->Vertex->p[1],
496 V->Vertex->p[1][nparam+1], nparam);
498 assert(sc.det == 1);
500 assert(V->Vertex->NbRows > 0);
501 Param_Vertex_Common_Denominator(V);
503 Matrix *Rays = zz2matrix(sc.rays);
505 t = offsets_to_integer_point(Rays, V->Vertex);
507 Vector *c = Vector_Alloc(3);
508 Inner_Product(Rays->p[0], Rays->p[1], 2, &c->p[0]);
509 Inner_Product(Rays->p[0], Rays->p[0], 2, &c->p[1]);
510 Inner_Product(Rays->p[1], Rays->p[1], 2, &c->p[2]);
512 mu_2d mu(degree, t[0], t[1], c->p[0], c->p[1], c->p[2]);
513 Vector_Free(c);
515 struct power power_r00(Rays->p[0][0], degree);
516 struct power power_r01(Rays->p[0][1], degree);
517 struct power power_r10(Rays->p[1][0], degree);
518 struct power power_r11(Rays->p[1][1], degree);
520 Value factor, tmp1, tmp2;
521 value_init(factor);
522 value_init(tmp1);
523 value_init(tmp2);
524 evalue *res = evalue_zero();
525 evalue *dx1 = evalue_dup(polynomial);
526 for (int i = 0; !EVALUE_IS_ZERO(*dx1); ++i) {
527 evalue *dx2 = evalue_dup(dx1);
528 for (int j = 0; !EVALUE_IS_ZERO(*dx2); ++j) {
529 evalue *cij = evalue_zero();
530 for (int n1 = 0; n1 <= i+j; ++n1) {
531 int n2 = i+j-n1;
532 value_set_si(factor, 0);
533 for (int k = max(0, i-n2); k <= i && k <= n1; ++k) {
534 int l = i-k;
535 value_multiply(tmp1, *power_r00[k], *power_r01[n1-k]);
536 value_multiply(tmp1, tmp1, *power_r10[l]);
537 value_multiply(tmp1, tmp1, *power_r11[n2-l]);
538 value_multiply(tmp1, tmp1, *binomial(n1, k));
539 value_multiply(tmp1, tmp1, *binomial(n2, l));
540 value_addto(factor, factor, tmp1);
542 if (value_zero_p(factor))
543 continue;
545 evalue *c = evalue_dup(mu.coefficient(n1, n2));
546 evalue_mul(c, factor);
547 eadd(c, cij);
548 evalue_free(c);
550 evalue *d = evalue_dup(dx2);
551 evalue_substitute(d, subs_0d);
552 emul(cij, d);
553 evalue_free(cij);
554 eadd(d, res);
555 evalue_free(d);
556 evalue_derive(dx2, 1);
558 evalue_free(dx2);
559 evalue_derive(dx1, 0);
561 evalue_free(dx1);
562 for (int i = 0; i < 2; ++i) {
563 evalue_free(subs_0d[i]);
564 subs_0d[i] = NULL;
565 evalue_free(t[i]);
567 delete [] t;
568 value_clear(factor);
569 value_clear(tmp1);
570 value_clear(tmp2);
571 Matrix_Free(Rays);
573 if (sc.sign < 0)
574 evalue_negate(res);
575 eadd(res, sum);
576 evalue_free(res);
579 evalue *summator_2d::summate_over_pdomain(Param_Polyhedron *PP,
580 unsigned *facets, Param_Domain *PD,
581 struct barvinok_options *options)
583 Param_Vertices *V;
584 int i, ix;
585 unsigned bx;
587 assert(PP->V->Vertex->NbRows == 2);
589 FORALL_PVertex_in_ParamPolyhedron(V, PD, PP) // _i internal counter
590 decompose_at_vertex(V, _i, options);
591 END_FORALL_PVertex_in_ParamPolyhedron;
593 Vector *normal = Vector_Alloc(2);
594 for (i = 0, ix = 0, bx = MSB; i < PP->Constraints->NbRows; ++i) {
595 Param_Domain *FD;
597 if (!(facets[ix] & bx)) {
598 NEXT(ix, bx);
599 continue;
602 Vector_Copy(PP->Constraints->p[i]+1, normal->p, 2);
603 if (value_zero_p(normal->p[0]) && value_zero_p(normal->p[1]))
604 continue;
606 FD = Param_Polyhedron_Facet(PP, PD, PP->Constraints->p[i]);
607 Vector_Normalize(normal->p, 2);
608 handle_facet(PP, FD, normal->p);
609 Param_Domain_Free(FD);
610 NEXT(ix, bx);
612 Vector_Free(normal);
614 integrate(PP, facets, PD);
616 return sum;
619 void summator_2d::handle_facet(Param_Polyhedron *PP, Param_Domain *FD,
620 Value *normal)
622 Param_Vertices *V;
623 int nbV = 0;
624 Param_Vertices *vertex[2];
625 Value det;
626 unsigned degree = total_degree(polynomial, 2);
628 FORALL_PVertex_in_ParamPolyhedron(V, FD, PP)
629 vertex[nbV++] = V;
630 END_FORALL_PVertex_in_ParamPolyhedron;
632 assert(nbV == 2);
634 /* We can take either vertex[0] or vertex[1];
635 * the result should be the same
637 Param_Vertex_Common_Denominator(vertex[0]);
639 /* The extra variable in front is the coordinate along the facet. */
640 Vector *coef_normal = Vector_Alloc(1 + nparam + 2);
641 Vector_Combine(vertex[0]->Vertex->p[0], vertex[0]->Vertex->p[1],
642 coef_normal->p+1, normal[0], normal[1], nparam+1);
643 value_assign(coef_normal->p[1+nparam+1], vertex[0]->Vertex->p[0][nparam+1]);
644 Vector_Normalize(coef_normal->p, coef_normal->Size);
646 Vector *base = Vector_Alloc(2);
647 value_oppose(base->p[0], normal[1]);
648 value_assign(base->p[1], normal[0]);
650 value_init(det);
651 Inner_Product(normal, normal, 2, &det);
653 Vector *s = Vector_Alloc(1+nparam+2);
654 value_multiply(s->p[1+nparam+1], coef_normal->p[1+nparam+1], det);
655 value_multiply(s->p[0], base->p[0], s->p[1+nparam+1]);
656 Vector_Scale(coef_normal->p+1, s->p+1, normal[0], nparam+1);
657 subs_1d[0] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
658 value_multiply(s->p[0], base->p[1], s->p[1+nparam+1]);
659 Vector_Scale(coef_normal->p+1, s->p+1, normal[1], nparam+1);
660 subs_1d[1] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
661 Vector_Free(s);
663 evalue *t;
664 if (value_one_p(coef_normal->p[coef_normal->Size-1]))
665 t = evalue_zero();
666 else {
667 Vector_Oppose(coef_normal->p+1, coef_normal->p+1, nparam+1);
668 t = fractional_part(coef_normal->p,
669 coef_normal->p[coef_normal->Size-1],
670 1+nparam, NULL);
672 Vector_Free(coef_normal);
674 mu_1d mu(degree, t);
676 struct power power_normal0(normal[0], degree);
677 struct power power_normal1(normal[1], degree);
678 struct power power_det(det, degree);
680 Value(factor);
681 value_init(factor);
682 evalue *res = evalue_zero();
683 evalue *dx1 = evalue_dup(polynomial);
684 for (int i = 0; !EVALUE_IS_ZERO(*dx1); ++i) {
685 evalue *dx2 = evalue_dup(dx1);
686 for (int j = 0; !EVALUE_IS_ZERO(*dx2); ++j) {
687 value_multiply(factor, *power_normal0[i], *power_normal1[j]);
688 if (value_notzero_p(factor)) {
689 value_multiply(factor, factor, *binomial(i+j, i));
691 evalue *c = evalue_dup(mu.coefficient(i+j));
692 evalue_mul_div(c, factor, *power_det[i+j]);
694 evalue *d = evalue_dup(dx2);
695 evalue_substitute(d, subs_1d);
696 emul(c, d);
697 evalue_free(c);
698 eadd(d, res);
699 evalue_free(d);
701 evalue_derive(dx2, 1);
703 evalue_free(dx2);
704 evalue_derive(dx1, 0);
706 evalue_free(dx1);
707 evalue_free(t);
708 for (int i = 0; i < 2; ++i) {
709 evalue_free(subs_1d[i]);
710 subs_1d[i] = NULL;
712 value_clear(factor);
713 evalue_anti_derive(res, 0);
715 Matrix *z = Matrix_Alloc(2, nparam+2);
716 Vector *fixed_z = Vector_Alloc(2);
717 for (int i = 0; i < 2; ++i) {
718 Vector_Combine(vertex[i]->Vertex->p[0], vertex[i]->Vertex->p[1],
719 z->p[i], base->p[0], base->p[1], nparam+1);
720 value_multiply(z->p[i][nparam+1],
721 det, vertex[i]->Vertex->p[0][nparam+1]);
722 Inner_Product(z->p[i], inner, nparam+1, &fixed_z->p[i]);
724 Vector_Free(base);
725 /* Put on a common denominator */
726 value_multiply(fixed_z->p[0], fixed_z->p[0], z->p[1][nparam+1]);
727 value_multiply(fixed_z->p[1], fixed_z->p[1], z->p[0][nparam+1]);
728 /* Make sure z->p[0] is smaller than z->p[1] (for an internal
729 * point of the chamber and hence for all parameter values in
730 * the chamber), to ensure we integrate in the right direction.
732 if (value_lt(fixed_z->p[1], fixed_z->p[0]))
733 Vector_Exchange(z->p[0], z->p[1], nparam+2);
734 Vector_Free(fixed_z);
735 value_clear(det);
737 subs_0d[1] = affine2evalue(z->p[1], z->p[1][nparam+1], nparam);
738 evalue *up = evalue_dup(res);
739 evalue_substitute(up, subs_0d+1);
740 evalue_free(subs_0d[1]);
742 subs_0d[1] = affine2evalue(z->p[0], z->p[0][nparam+1], nparam);
743 evalue_substitute(res, subs_0d+1);
744 evalue_negate(res);
745 eadd(up, res);
746 evalue_free(subs_0d[1]);
747 subs_0d[1] = NULL;
748 evalue_free(up);
750 Matrix_Free(z);
752 eadd(res, sum);
753 evalue_free(res);
756 /* Integrate the polynomial over the whole polygon using
757 * the Green-Stokes theorem.
759 void summator_2d::integrate(Param_Polyhedron *PP, unsigned *facets,
760 Param_Domain *PD)
762 Value tmp;
763 evalue *res = evalue_zero();
764 int i, ix;
765 unsigned bx;
767 evalue *I = evalue_dup(polynomial);
768 evalue_anti_derive(I, 0);
770 value_init(tmp);
771 Vector *normal = Vector_Alloc(2);
772 Vector *dir = Vector_Alloc(2);
773 Matrix *v0v1 = Matrix_Alloc(2, nparam+2);
774 Vector *f_v0v1 = Vector_Alloc(2);
775 Vector *s = Vector_Alloc(1+nparam+2);
776 for (i = 0, ix = 0, bx = MSB; i < PP->Constraints->NbRows; ++i) {
777 Param_Domain *FD;
778 int nbV = 0;
779 Param_Vertices *vertex[2];
781 if (!(facets[ix] & bx)) {
782 NEXT(ix, bx);
783 continue;
786 Vector_Copy(PP->Constraints->p[i]+1, normal->p, 2);
788 if (value_zero_p(normal->p[0]))
789 continue;
791 Vector_Normalize(normal->p, 2);
792 value_assign(dir->p[0], normal->p[1]);
793 value_oppose(dir->p[1], normal->p[0]);
795 FD = Param_Polyhedron_Facet(PP, PD, PP->Constraints->p[i]);
797 FORALL_PVertex_in_ParamPolyhedron(V, FD, PP)
798 vertex[nbV++] = V;
799 END_FORALL_PVertex_in_ParamPolyhedron;
801 assert(nbV == 2);
803 Param_Vertex_Common_Denominator(vertex[0]);
804 Param_Vertex_Common_Denominator(vertex[1]);
806 value_oppose(tmp, vertex[1]->Vertex->p[0][nparam+1]);
807 for (int i = 0; i < 2; ++i)
808 Vector_Combine(vertex[1]->Vertex->p[i],
809 vertex[0]->Vertex->p[i],
810 v0v1->p[i],
811 vertex[0]->Vertex->p[0][nparam+1], tmp, nparam+1);
812 value_multiply(v0v1->p[0][nparam+1],
813 vertex[0]->Vertex->p[0][nparam+1],
814 vertex[1]->Vertex->p[0][nparam+1]);
815 value_assign(v0v1->p[1][nparam+1], v0v1->p[0][nparam+1]);
817 /* Order vertices to ensure we integrate in the right
818 * direction, i.e., with the polytope "on the left".
820 for (int i = 0; i < 2; ++i)
821 Inner_Product(v0v1->p[i], inner, nparam+1, &f_v0v1->p[i]);
823 Inner_Product(dir->p, f_v0v1->p, 2, &tmp);
824 if (value_neg_p(tmp)) {
825 Param_Vertices *PV = vertex[0];
826 vertex[0] = vertex[1];
827 vertex[1] = PV;
828 for (int i = 0; i < 2; ++i)
829 Vector_Oppose(v0v1->p[i], v0v1->p[i], nparam+1);
831 value_oppose(tmp, normal->p[0]);
832 if (value_neg_p(tmp)) {
833 value_oppose(tmp, tmp);
834 Vector_Oppose(v0v1->p[1], v0v1->p[1], nparam+1);
836 value_multiply(tmp, tmp, v0v1->p[1][nparam+1]);
837 evalue *top = affine2evalue(v0v1->p[1], tmp, nparam);
839 value_multiply(s->p[0], normal->p[1], vertex[0]->Vertex->p[0][nparam+1]);
840 Vector_Copy(vertex[0]->Vertex->p[0], s->p+1, nparam+2);
841 subs_1d[0] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
842 value_multiply(s->p[0], normal->p[0], vertex[0]->Vertex->p[0][nparam+1]);
843 value_oppose(s->p[0], s->p[0]);
844 Vector_Copy(vertex[0]->Vertex->p[1], s->p+1, nparam+2);
845 subs_1d[1] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
847 evalue *d = evalue_dup(I);
848 evalue_substitute(d, subs_1d);
849 evalue_anti_derive(d, 0);
851 evalue_free(subs_1d[0]);
852 evalue_free(subs_1d[1]);
854 subs_0d[1] = top;
855 evalue_substitute(d, subs_0d+1);
856 evalue_mul(d, dir->p[1]);
857 evalue_free(subs_0d[1]);
859 eadd(d, res);
860 evalue_free(d);
862 Param_Domain_Free(FD);
863 NEXT(ix, bx);
865 Vector_Free(s);
866 Vector_Free(f_v0v1);
867 Matrix_Free(v0v1);
868 Vector_Free(normal);
869 Vector_Free(dir);
870 value_clear(tmp);
871 evalue_free(I);
873 eadd(res, sum);
874 evalue_free(res);
877 evalue *summate_over_1d_pdomain(evalue *e,
878 Param_Polyhedron *PP, Param_Domain *PD,
879 Value *inner,
880 struct barvinok_options *options)
882 Param_Vertices *V;
883 int nbV = 0;
884 Param_Vertices *vertex[2];
885 unsigned nparam = PP->V->Vertex->NbColumns-2;
886 evalue *subs_0d[1+nparam];
887 evalue *a[2];
888 evalue *t[2];
889 unsigned degree = total_degree(e, 1);
891 for (int i = 0; i < nparam; ++i)
892 subs_0d[1+i] = evalue_var(i);
894 FORALL_PVertex_in_ParamPolyhedron(V, PD, PP)
895 vertex[nbV++] = V;
896 END_FORALL_PVertex_in_ParamPolyhedron;
897 assert(nbV == 2);
899 Vector *fixed = Vector_Alloc(2);
900 for (int i = 0; i < 2; ++i) {
901 Inner_Product(vertex[i]->Vertex->p[0], inner, nparam+1, &fixed->p[i]);
902 value_multiply(fixed->p[i],
903 fixed->p[i], vertex[1-i]->Vertex->p[0][nparam+1]);
905 if (value_lt(fixed->p[1], fixed->p[0])) {
906 V = vertex[0];
907 vertex[0] = vertex[1];
908 vertex[1] = V;
910 Vector_Free(fixed);
912 Vector *coef = Vector_Alloc(nparam+1);
913 for (int i = 0; i < 2; ++i)
914 a[i] = affine2evalue(vertex[i]->Vertex->p[0],
915 vertex[i]->Vertex->p[0][nparam+1], nparam);
916 if (value_one_p(vertex[0]->Vertex->p[0][nparam+1]))
917 t[0] = evalue_zero();
918 else {
919 Vector_Oppose(vertex[0]->Vertex->p[0], coef->p, nparam+1);
920 t[0] = fractional_part(coef->p, vertex[0]->Vertex->p[0][nparam+1],
921 nparam, NULL);
923 if (value_one_p(vertex[1]->Vertex->p[0][nparam+1]))
924 t[1] = evalue_zero();
925 else {
926 Vector_Copy(vertex[1]->Vertex->p[0], coef->p, nparam+1);
927 t[1] = fractional_part(coef->p, vertex[1]->Vertex->p[0][nparam+1],
928 nparam, NULL);
930 Vector_Free(coef);
932 evalue *I = evalue_dup(e);
933 evalue_anti_derive(I, 0);
934 evalue *up = evalue_dup(I);
935 subs_0d[0] = a[1];
936 evalue_substitute(up, subs_0d);
938 subs_0d[0] = a[0];
939 evalue_substitute(I, subs_0d);
940 evalue_negate(I);
941 eadd(up, I);
942 evalue_free(up);
944 evalue *res = I;
946 mu_1d mu0(degree, t[0]);
947 mu_1d mu1(degree, t[1]);
949 evalue *dx = evalue_dup(e);
950 for (int n = 0; !EVALUE_IS_ZERO(*dx); ++n) {
951 evalue *d;
953 d = evalue_dup(dx);
954 subs_0d[0] = a[0];
955 evalue_substitute(d, subs_0d);
956 emul(mu0.coefficient(n), d);
957 eadd(d, res);
958 evalue_free(d);
960 d = evalue_dup(dx);
961 subs_0d[0] = a[1];
962 evalue_substitute(d, subs_0d);
963 emul(mu1.coefficient(n), d);
964 if (n % 2)
965 evalue_negate(d);
966 eadd(d, res);
967 evalue_free(d);
969 evalue_derive(dx, 0);
971 evalue_free(dx);
973 for (int i = 0; i < nparam; ++i)
974 evalue_free(subs_0d[1+i]);
976 for (int i = 0; i < 2; ++i) {
977 evalue_free(a[i]);
978 evalue_free(t[i]);
981 return res;
984 #define INT_BITS (sizeof(unsigned) * 8)
986 static unsigned *active_constraints(Param_Polyhedron *PP, Param_Domain *D)
988 int len = (PP->Constraints->NbRows+INT_BITS-1)/INT_BITS;
989 unsigned *facets = (unsigned *)calloc(len, sizeof(unsigned));
990 Param_Vertices *V;
992 FORALL_PVertex_in_ParamPolyhedron(V, D, PP)
993 if (!V->Facets)
994 Param_Vertex_Set_Facets(PP, V);
995 for (int i = 0; i < len; ++i)
996 facets[i] |= V->Facets[i];
997 END_FORALL_PVertex_in_ParamPolyhedron;
999 return facets;
1002 static evalue *summate_over_domain(evalue *e, int nvar, Polyhedron *D,
1003 struct barvinok_options *options)
1005 Polyhedron *U;
1006 Param_Polyhedron *PP;
1007 evalue *res;
1008 int nd = -1;
1009 unsigned MaxRays;
1010 struct evalue_section *s;
1011 Param_Domain *PD;
1013 MaxRays = options->MaxRays;
1014 POL_UNSET(options->MaxRays, POL_INTEGER);
1016 U = Universe_Polyhedron(D->Dimension - nvar);
1017 PP = Polyhedron2Param_Polyhedron(D, U, options);
1019 for (nd = 0, PD = PP->D; PD; ++nd, PD = PD->next);
1020 s = ALLOCN(struct evalue_section, nd);
1022 Polyhedron *TC = true_context(D, U, MaxRays);
1023 FORALL_REDUCED_DOMAIN(PP, TC, nd, options, i, PD, rVD)
1024 unsigned *facets;
1026 facets = active_constraints(PP, PD);
1028 Vector *inner = inner_point(rVD);
1029 s[i].D = rVD;
1031 if (nvar == 1) {
1032 s[i].E = summate_over_1d_pdomain(e, PP, PD, inner->p+1, options);
1033 } else if (nvar == 2) {
1034 summator_2d s2d(e, PP, inner->p+1, rVD->Dimension);
1036 s[i].E = s2d.summate_over_pdomain(PP, facets, PD, options);
1039 Vector_Free(inner);
1040 free(facets);
1041 END_FORALL_REDUCED_DOMAIN
1042 Polyhedron_Free(TC);
1043 Polyhedron_Free(U);
1044 Param_Polyhedron_Free(PP);
1046 options->MaxRays = MaxRays;
1048 res = evalue_from_section_array(s, nd);
1049 free(s);
1051 return res;
1054 evalue *euler_summate(evalue *e, unsigned nvar,
1055 struct barvinok_options *options)
1057 int i;
1058 evalue *res;
1060 assert(nvar <= 2);
1062 assert(nvar >= 0);
1063 if (nvar == 0 || EVALUE_IS_ZERO(*e))
1064 return evalue_dup(e);
1066 assert(value_zero_p(e->d));
1067 assert(e->x.p->type == partition);
1069 res = evalue_zero();
1071 for (i = 0; i < e->x.p->size/2; ++i) {
1072 evalue *t;
1073 t = summate_over_domain(&e->x.p->arr[2*i+1], nvar,
1074 EVALUE_DOMAIN(e->x.p->arr[2*i]), options);
1075 eadd(t, res);
1076 evalue_free(t);
1079 return res;