barvinok_bound: add --iterate options for evaluating evalue in each point
[barvinok.git] / euler.cc
blobb56d203299a4c61a551d6624982cc8366d2a27dd
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 == 1) {
370 free(p);
371 evalue_set_si(poly, 0, 1);
372 return;
374 if (p->size == 2) {
375 value_clear(poly->d);
376 *poly = p->arr[1];
377 free(p);
378 return;
381 p->size--;
382 Value factor;
383 value_init(factor);
384 for (int i = 0; i < p->size; ++i) {
385 value_set_si(factor, i+1);
386 p->arr[i] = p->arr[i+1];
387 evalue_mul(&p->arr[i], factor);
389 value_clear(factor);
392 /* Check whether e is constant with respect to variable var */
393 static int evalue_is_constant(evalue *e, int var)
395 int i;
397 if (value_notzero_p(e->d))
398 return 1;
399 if (e->x.p->type == polynomial && e->x.p->pos-1 == var)
400 return 0;
401 assert(e->x.p->type == polynomial ||
402 e->x.p->type == fractional ||
403 e->x.p->type == flooring);
404 for (i = 0; i < e->x.p->size; ++i)
405 if (!evalue_is_constant(&e->x.p->arr[i], var))
406 return 0;
407 return 1;
410 /* Replaces poly by its anti-derivative with constant 0 along variable var */
411 static void evalue_anti_derive(evalue *poly, int var)
413 enode *p;
415 if (value_zero_p(poly->d) &&
416 poly->x.p->type == polynomial && poly->x.p->pos-1 < var) {
417 for (int i = 0; i < poly->x.p->size; ++i)
418 evalue_anti_derive(&poly->x.p->arr[i], var);
419 reduce_evalue(poly);
420 return;
423 if (evalue_is_constant(poly, var)) {
424 p = new_enode(polynomial, 2, 1+var);
425 evalue_set_si(&p->arr[0], 0, 1);
426 value_clear(p->arr[1].d);
427 p->arr[1] = *poly;
428 value_init(poly->d);
429 poly->x.p = p;
430 return;
432 assert(poly->x.p->type == polynomial);
434 p = new_enode(polynomial, poly->x.p->size+1, 1+var);
435 evalue_set_si(&p->arr[0], 0, 1);
436 for (int i = 0; i < poly->x.p->size; ++i) {
437 value_clear(p->arr[1+i].d);
438 p->arr[1+i] = poly->x.p->arr[i];
439 value_set_si(poly->d, 1+i);
440 evalue_div(&p->arr[1+i], poly->d);
442 free(poly->x.p);
443 poly->x.p = p;
444 value_set_si(poly->d, 0);
447 /* Computes offsets in the basis given by the rays of the cone
448 * to the integer point in the fundamental parallelepiped of
449 * the cone.
450 * The resulting evalues contain only the parameters as variables.
452 evalue **offsets_to_integer_point(Matrix *Rays, Matrix *vertex)
454 unsigned nparam = vertex->NbColumns-2;
455 evalue **t = new evalue *[2];
457 if (value_one_p(vertex->p[0][nparam+1])) {
458 t[0] = evalue_zero();
459 t[1] = evalue_zero();
460 } else {
461 Matrix *R2 = Matrix_Copy(Rays);
462 Matrix_Transposition(R2);
463 Matrix *inv = Matrix_Alloc(Rays->NbColumns, Rays->NbRows);
464 int ok = Matrix_Inverse(R2, inv);
465 assert(ok);
466 Matrix_Free(R2);
468 /* We want the fractional part of the negative relative coordinates */
469 Vector_Oppose(inv->p[0], inv->p[0], inv->NbColumns);
470 Vector_Oppose(inv->p[1], inv->p[1], inv->NbColumns);
472 Matrix *neg_rel = Matrix_Alloc(2, nparam+1);
473 vertex->NbColumns--;
474 Matrix_Product(inv, vertex, neg_rel);
475 Matrix_Free(inv);
476 vertex->NbColumns++;
477 t[0] = fractional_part(neg_rel->p[0], vertex->p[0][nparam+1],
478 nparam, NULL);
479 t[1] = fractional_part(neg_rel->p[1], vertex->p[0][nparam+1],
480 nparam, NULL);
481 Matrix_Free(neg_rel);
484 return t;
488 * Called from decompose_at_vertex.
490 * Handles a cone in the signed decomposition of the supporting
491 * cone of a vertex. The cone is assumed to be unimodular.
493 void summator_2d::handle(const signed_cone& sc, barvinok_options *options)
495 evalue **t;
496 unsigned degree = total_degree(polynomial, 2);
498 subs_0d[0] = affine2evalue(V->Vertex->p[0],
499 V->Vertex->p[0][nparam+1], nparam);
500 subs_0d[1] = affine2evalue(V->Vertex->p[1],
501 V->Vertex->p[1][nparam+1], nparam);
503 assert(sc.det == 1);
505 assert(V->Vertex->NbRows > 0);
506 Param_Vertex_Common_Denominator(V);
508 Matrix *Rays = zz2matrix(sc.rays);
510 t = offsets_to_integer_point(Rays, V->Vertex);
512 Vector *c = Vector_Alloc(3);
513 Inner_Product(Rays->p[0], Rays->p[1], 2, &c->p[0]);
514 Inner_Product(Rays->p[0], Rays->p[0], 2, &c->p[1]);
515 Inner_Product(Rays->p[1], Rays->p[1], 2, &c->p[2]);
517 mu_2d mu(degree, t[0], t[1], c->p[0], c->p[1], c->p[2]);
518 Vector_Free(c);
520 struct power power_r00(Rays->p[0][0], degree);
521 struct power power_r01(Rays->p[0][1], degree);
522 struct power power_r10(Rays->p[1][0], degree);
523 struct power power_r11(Rays->p[1][1], degree);
525 Value factor, tmp1, tmp2;
526 value_init(factor);
527 value_init(tmp1);
528 value_init(tmp2);
529 evalue *res = evalue_zero();
530 evalue *dx1 = evalue_dup(polynomial);
531 for (int i = 0; !EVALUE_IS_ZERO(*dx1); ++i) {
532 evalue *dx2 = evalue_dup(dx1);
533 for (int j = 0; !EVALUE_IS_ZERO(*dx2); ++j) {
534 evalue *cij = evalue_zero();
535 for (int n1 = 0; n1 <= i+j; ++n1) {
536 int n2 = i+j-n1;
537 value_set_si(factor, 0);
538 for (int k = max(0, i-n2); k <= i && k <= n1; ++k) {
539 int l = i-k;
540 value_multiply(tmp1, *power_r00[k], *power_r01[n1-k]);
541 value_multiply(tmp1, tmp1, *power_r10[l]);
542 value_multiply(tmp1, tmp1, *power_r11[n2-l]);
543 value_multiply(tmp1, tmp1, *binomial(n1, k));
544 value_multiply(tmp1, tmp1, *binomial(n2, l));
545 value_addto(factor, factor, tmp1);
547 if (value_zero_p(factor))
548 continue;
550 evalue *c = evalue_dup(mu.coefficient(n1, n2));
551 evalue_mul(c, factor);
552 eadd(c, cij);
553 evalue_free(c);
555 evalue *d = evalue_dup(dx2);
556 evalue_substitute(d, subs_0d);
557 emul(cij, d);
558 evalue_free(cij);
559 eadd(d, res);
560 evalue_free(d);
561 evalue_derive(dx2, 1);
563 evalue_free(dx2);
564 evalue_derive(dx1, 0);
566 evalue_free(dx1);
567 for (int i = 0; i < 2; ++i) {
568 evalue_free(subs_0d[i]);
569 subs_0d[i] = NULL;
570 evalue_free(t[i]);
572 delete [] t;
573 value_clear(factor);
574 value_clear(tmp1);
575 value_clear(tmp2);
576 Matrix_Free(Rays);
578 if (sc.sign < 0)
579 evalue_negate(res);
580 eadd(res, sum);
581 evalue_free(res);
584 evalue *summator_2d::summate_over_pdomain(Param_Polyhedron *PP,
585 unsigned *facets, Param_Domain *PD,
586 struct barvinok_options *options)
588 Param_Vertices *V;
589 int i, ix;
590 unsigned bx;
592 assert(PP->V->Vertex->NbRows == 2);
594 FORALL_PVertex_in_ParamPolyhedron(V, PD, PP) // _i internal counter
595 decompose_at_vertex(V, _i, options);
596 END_FORALL_PVertex_in_ParamPolyhedron;
598 Vector *normal = Vector_Alloc(2);
599 for (i = 0, ix = 0, bx = MSB; i < PP->Constraints->NbRows; ++i) {
600 Param_Domain *FD;
602 if (!(facets[ix] & bx)) {
603 NEXT(ix, bx);
604 continue;
607 Vector_Copy(PP->Constraints->p[i]+1, normal->p, 2);
608 if (value_zero_p(normal->p[0]) && value_zero_p(normal->p[1]))
609 continue;
611 FD = Param_Polyhedron_Facet(PP, PD, PP->Constraints->p[i]);
612 Vector_Normalize(normal->p, 2);
613 handle_facet(PP, FD, normal->p);
614 Param_Domain_Free(FD);
615 NEXT(ix, bx);
617 Vector_Free(normal);
619 integrate(PP, facets, PD);
621 return sum;
624 void summator_2d::handle_facet(Param_Polyhedron *PP, Param_Domain *FD,
625 Value *normal)
627 Param_Vertices *V;
628 int nbV = 0;
629 Param_Vertices *vertex[2];
630 Value det;
631 unsigned degree = total_degree(polynomial, 2);
633 FORALL_PVertex_in_ParamPolyhedron(V, FD, PP)
634 vertex[nbV++] = V;
635 END_FORALL_PVertex_in_ParamPolyhedron;
637 assert(nbV == 2);
639 /* We can take either vertex[0] or vertex[1];
640 * the result should be the same
642 Param_Vertex_Common_Denominator(vertex[0]);
644 /* The extra variable in front is the coordinate along the facet. */
645 Vector *coef_normal = Vector_Alloc(1 + nparam + 2);
646 Vector_Combine(vertex[0]->Vertex->p[0], vertex[0]->Vertex->p[1],
647 coef_normal->p+1, normal[0], normal[1], nparam+1);
648 value_assign(coef_normal->p[1+nparam+1], vertex[0]->Vertex->p[0][nparam+1]);
649 Vector_Normalize(coef_normal->p, coef_normal->Size);
651 Vector *base = Vector_Alloc(2);
652 value_oppose(base->p[0], normal[1]);
653 value_assign(base->p[1], normal[0]);
655 value_init(det);
656 Inner_Product(normal, normal, 2, &det);
658 Vector *s = Vector_Alloc(1+nparam+2);
659 value_multiply(s->p[1+nparam+1], coef_normal->p[1+nparam+1], det);
660 value_multiply(s->p[0], base->p[0], s->p[1+nparam+1]);
661 Vector_Scale(coef_normal->p+1, s->p+1, normal[0], nparam+1);
662 subs_1d[0] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
663 value_multiply(s->p[0], base->p[1], s->p[1+nparam+1]);
664 Vector_Scale(coef_normal->p+1, s->p+1, normal[1], nparam+1);
665 subs_1d[1] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
666 Vector_Free(s);
668 evalue *t;
669 if (value_one_p(coef_normal->p[coef_normal->Size-1]))
670 t = evalue_zero();
671 else {
672 Vector_Oppose(coef_normal->p+1, coef_normal->p+1, nparam+1);
673 t = fractional_part(coef_normal->p,
674 coef_normal->p[coef_normal->Size-1],
675 1+nparam, NULL);
677 Vector_Free(coef_normal);
679 mu_1d mu(degree, t);
681 struct power power_normal0(normal[0], degree);
682 struct power power_normal1(normal[1], degree);
683 struct power power_det(det, degree);
685 Value(factor);
686 value_init(factor);
687 evalue *res = evalue_zero();
688 evalue *dx1 = evalue_dup(polynomial);
689 for (int i = 0; !EVALUE_IS_ZERO(*dx1); ++i) {
690 evalue *dx2 = evalue_dup(dx1);
691 for (int j = 0; !EVALUE_IS_ZERO(*dx2); ++j) {
692 value_multiply(factor, *power_normal0[i], *power_normal1[j]);
693 if (value_notzero_p(factor)) {
694 value_multiply(factor, factor, *binomial(i+j, i));
696 evalue *c = evalue_dup(mu.coefficient(i+j));
697 evalue_mul_div(c, factor, *power_det[i+j]);
699 evalue *d = evalue_dup(dx2);
700 evalue_substitute(d, subs_1d);
701 emul(c, d);
702 evalue_free(c);
703 eadd(d, res);
704 evalue_free(d);
706 evalue_derive(dx2, 1);
708 evalue_free(dx2);
709 evalue_derive(dx1, 0);
711 evalue_free(dx1);
712 evalue_free(t);
713 for (int i = 0; i < 2; ++i) {
714 evalue_free(subs_1d[i]);
715 subs_1d[i] = NULL;
717 value_clear(factor);
718 evalue_anti_derive(res, 0);
720 Matrix *z = Matrix_Alloc(2, nparam+2);
721 Vector *fixed_z = Vector_Alloc(2);
722 for (int i = 0; i < 2; ++i) {
723 Vector_Combine(vertex[i]->Vertex->p[0], vertex[i]->Vertex->p[1],
724 z->p[i], base->p[0], base->p[1], nparam+1);
725 value_multiply(z->p[i][nparam+1],
726 det, vertex[i]->Vertex->p[0][nparam+1]);
727 Inner_Product(z->p[i], inner, nparam+1, &fixed_z->p[i]);
729 Vector_Free(base);
730 /* Put on a common denominator */
731 value_multiply(fixed_z->p[0], fixed_z->p[0], z->p[1][nparam+1]);
732 value_multiply(fixed_z->p[1], fixed_z->p[1], z->p[0][nparam+1]);
733 /* Make sure z->p[0] is smaller than z->p[1] (for an internal
734 * point of the chamber and hence for all parameter values in
735 * the chamber), to ensure we integrate in the right direction.
737 if (value_lt(fixed_z->p[1], fixed_z->p[0]))
738 Vector_Exchange(z->p[0], z->p[1], nparam+2);
739 Vector_Free(fixed_z);
740 value_clear(det);
742 subs_0d[1] = affine2evalue(z->p[1], z->p[1][nparam+1], nparam);
743 evalue *up = evalue_dup(res);
744 evalue_substitute(up, subs_0d+1);
745 evalue_free(subs_0d[1]);
747 subs_0d[1] = affine2evalue(z->p[0], z->p[0][nparam+1], nparam);
748 evalue_substitute(res, subs_0d+1);
749 evalue_negate(res);
750 eadd(up, res);
751 evalue_free(subs_0d[1]);
752 subs_0d[1] = NULL;
753 evalue_free(up);
755 Matrix_Free(z);
757 eadd(res, sum);
758 evalue_free(res);
761 /* Integrate the polynomial over the whole polygon using
762 * the Green-Stokes theorem.
764 void summator_2d::integrate(Param_Polyhedron *PP, unsigned *facets,
765 Param_Domain *PD)
767 Value tmp;
768 evalue *res = evalue_zero();
769 int i, ix;
770 unsigned bx;
772 evalue *I = evalue_dup(polynomial);
773 evalue_anti_derive(I, 0);
775 value_init(tmp);
776 Vector *normal = Vector_Alloc(2);
777 Vector *dir = Vector_Alloc(2);
778 Matrix *v0v1 = Matrix_Alloc(2, nparam+2);
779 Vector *f_v0v1 = Vector_Alloc(2);
780 Vector *s = Vector_Alloc(1+nparam+2);
781 for (i = 0, ix = 0, bx = MSB; i < PP->Constraints->NbRows; ++i) {
782 Param_Domain *FD;
783 int nbV = 0;
784 Param_Vertices *vertex[2];
786 if (!(facets[ix] & bx)) {
787 NEXT(ix, bx);
788 continue;
791 Vector_Copy(PP->Constraints->p[i]+1, normal->p, 2);
793 if (value_zero_p(normal->p[0]))
794 continue;
796 Vector_Normalize(normal->p, 2);
797 value_assign(dir->p[0], normal->p[1]);
798 value_oppose(dir->p[1], normal->p[0]);
800 FD = Param_Polyhedron_Facet(PP, PD, PP->Constraints->p[i]);
802 FORALL_PVertex_in_ParamPolyhedron(V, FD, PP)
803 vertex[nbV++] = V;
804 END_FORALL_PVertex_in_ParamPolyhedron;
806 assert(nbV == 2);
808 Param_Vertex_Common_Denominator(vertex[0]);
809 Param_Vertex_Common_Denominator(vertex[1]);
811 value_oppose(tmp, vertex[1]->Vertex->p[0][nparam+1]);
812 for (int i = 0; i < 2; ++i)
813 Vector_Combine(vertex[1]->Vertex->p[i],
814 vertex[0]->Vertex->p[i],
815 v0v1->p[i],
816 vertex[0]->Vertex->p[0][nparam+1], tmp, nparam+1);
817 value_multiply(v0v1->p[0][nparam+1],
818 vertex[0]->Vertex->p[0][nparam+1],
819 vertex[1]->Vertex->p[0][nparam+1]);
820 value_assign(v0v1->p[1][nparam+1], v0v1->p[0][nparam+1]);
822 /* Order vertices to ensure we integrate in the right
823 * direction, i.e., with the polytope "on the left".
825 for (int i = 0; i < 2; ++i)
826 Inner_Product(v0v1->p[i], inner, nparam+1, &f_v0v1->p[i]);
828 Inner_Product(dir->p, f_v0v1->p, 2, &tmp);
829 if (value_neg_p(tmp)) {
830 Param_Vertices *PV = vertex[0];
831 vertex[0] = vertex[1];
832 vertex[1] = PV;
833 for (int i = 0; i < 2; ++i)
834 Vector_Oppose(v0v1->p[i], v0v1->p[i], nparam+1);
836 value_oppose(tmp, normal->p[0]);
837 if (value_neg_p(tmp)) {
838 value_oppose(tmp, tmp);
839 Vector_Oppose(v0v1->p[1], v0v1->p[1], nparam+1);
841 value_multiply(tmp, tmp, v0v1->p[1][nparam+1]);
842 evalue *top = affine2evalue(v0v1->p[1], tmp, nparam);
844 value_multiply(s->p[0], normal->p[1], vertex[0]->Vertex->p[0][nparam+1]);
845 Vector_Copy(vertex[0]->Vertex->p[0], s->p+1, nparam+2);
846 subs_1d[0] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
847 value_multiply(s->p[0], normal->p[0], vertex[0]->Vertex->p[0][nparam+1]);
848 value_oppose(s->p[0], s->p[0]);
849 Vector_Copy(vertex[0]->Vertex->p[1], s->p+1, nparam+2);
850 subs_1d[1] = affine2evalue(s->p, s->p[1+nparam+1], 1+nparam);
852 evalue *d = evalue_dup(I);
853 evalue_substitute(d, subs_1d);
854 evalue_anti_derive(d, 0);
856 evalue_free(subs_1d[0]);
857 evalue_free(subs_1d[1]);
859 subs_0d[1] = top;
860 evalue_substitute(d, subs_0d+1);
861 evalue_mul(d, dir->p[1]);
862 evalue_free(subs_0d[1]);
864 eadd(d, res);
865 evalue_free(d);
867 Param_Domain_Free(FD);
868 NEXT(ix, bx);
870 Vector_Free(s);
871 Vector_Free(f_v0v1);
872 Matrix_Free(v0v1);
873 Vector_Free(normal);
874 Vector_Free(dir);
875 value_clear(tmp);
876 evalue_free(I);
878 eadd(res, sum);
879 evalue_free(res);
882 evalue *summate_over_1d_pdomain(evalue *e,
883 Param_Polyhedron *PP, Param_Domain *PD,
884 Value *inner,
885 struct barvinok_options *options)
887 Param_Vertices *V;
888 int nbV = 0;
889 Param_Vertices *vertex[2];
890 unsigned nparam = PP->V->Vertex->NbColumns-2;
891 evalue *subs_0d[1+nparam];
892 evalue *a[2];
893 evalue *t[2];
894 unsigned degree = total_degree(e, 1);
896 for (int i = 0; i < nparam; ++i)
897 subs_0d[1+i] = evalue_var(i);
899 FORALL_PVertex_in_ParamPolyhedron(V, PD, PP)
900 vertex[nbV++] = V;
901 END_FORALL_PVertex_in_ParamPolyhedron;
902 assert(nbV == 2);
904 Vector *fixed = Vector_Alloc(2);
905 for (int i = 0; i < 2; ++i) {
906 Inner_Product(vertex[i]->Vertex->p[0], inner, nparam+1, &fixed->p[i]);
907 value_multiply(fixed->p[i],
908 fixed->p[i], vertex[1-i]->Vertex->p[0][nparam+1]);
910 if (value_lt(fixed->p[1], fixed->p[0])) {
911 V = vertex[0];
912 vertex[0] = vertex[1];
913 vertex[1] = V;
915 Vector_Free(fixed);
917 Vector *coef = Vector_Alloc(nparam+1);
918 for (int i = 0; i < 2; ++i)
919 a[i] = affine2evalue(vertex[i]->Vertex->p[0],
920 vertex[i]->Vertex->p[0][nparam+1], nparam);
921 if (value_one_p(vertex[0]->Vertex->p[0][nparam+1]))
922 t[0] = evalue_zero();
923 else {
924 Vector_Oppose(vertex[0]->Vertex->p[0], coef->p, nparam+1);
925 t[0] = fractional_part(coef->p, vertex[0]->Vertex->p[0][nparam+1],
926 nparam, NULL);
928 if (value_one_p(vertex[1]->Vertex->p[0][nparam+1]))
929 t[1] = evalue_zero();
930 else {
931 Vector_Copy(vertex[1]->Vertex->p[0], coef->p, nparam+1);
932 t[1] = fractional_part(coef->p, vertex[1]->Vertex->p[0][nparam+1],
933 nparam, NULL);
935 Vector_Free(coef);
937 evalue *I = evalue_dup(e);
938 evalue_anti_derive(I, 0);
939 evalue *up = evalue_dup(I);
940 subs_0d[0] = a[1];
941 evalue_substitute(up, subs_0d);
943 subs_0d[0] = a[0];
944 evalue_substitute(I, subs_0d);
945 evalue_negate(I);
946 eadd(up, I);
947 evalue_free(up);
949 evalue *res = I;
951 mu_1d mu0(degree, t[0]);
952 mu_1d mu1(degree, t[1]);
954 evalue *dx = evalue_dup(e);
955 for (int n = 0; !EVALUE_IS_ZERO(*dx); ++n) {
956 evalue *d;
958 d = evalue_dup(dx);
959 subs_0d[0] = a[0];
960 evalue_substitute(d, subs_0d);
961 emul(mu0.coefficient(n), d);
962 eadd(d, res);
963 evalue_free(d);
965 d = evalue_dup(dx);
966 subs_0d[0] = a[1];
967 evalue_substitute(d, subs_0d);
968 emul(mu1.coefficient(n), d);
969 if (n % 2)
970 evalue_negate(d);
971 eadd(d, res);
972 evalue_free(d);
974 evalue_derive(dx, 0);
976 evalue_free(dx);
978 for (int i = 0; i < nparam; ++i)
979 evalue_free(subs_0d[1+i]);
981 for (int i = 0; i < 2; ++i) {
982 evalue_free(a[i]);
983 evalue_free(t[i]);
986 return res;
989 #define INT_BITS (sizeof(unsigned) * 8)
991 static unsigned *active_constraints(Param_Polyhedron *PP, Param_Domain *D)
993 int len = (PP->Constraints->NbRows+INT_BITS-1)/INT_BITS;
994 unsigned *facets = (unsigned *)calloc(len, sizeof(unsigned));
995 Param_Vertices *V;
997 FORALL_PVertex_in_ParamPolyhedron(V, D, PP)
998 if (!V->Facets)
999 Param_Vertex_Set_Facets(PP, V);
1000 for (int i = 0; i < len; ++i)
1001 facets[i] |= V->Facets[i];
1002 END_FORALL_PVertex_in_ParamPolyhedron;
1004 return facets;
1007 static evalue *summate_over_domain(evalue *e, int nvar, Polyhedron *D,
1008 struct barvinok_options *options)
1010 Polyhedron *U;
1011 Param_Polyhedron *PP;
1012 evalue *res;
1013 int nd = -1;
1014 unsigned MaxRays;
1015 struct evalue_section *s;
1016 Param_Domain *PD;
1018 MaxRays = options->MaxRays;
1019 POL_UNSET(options->MaxRays, POL_INTEGER);
1021 U = Universe_Polyhedron(D->Dimension - nvar);
1022 PP = Polyhedron2Param_Polyhedron(D, U, options);
1024 for (nd = 0, PD = PP->D; PD; ++nd, PD = PD->next);
1025 s = ALLOCN(struct evalue_section, nd);
1027 Polyhedron *TC = true_context(D, U, MaxRays);
1028 FORALL_REDUCED_DOMAIN(PP, TC, nd, options, i, PD, rVD)
1029 unsigned *facets;
1031 facets = active_constraints(PP, PD);
1033 Vector *inner = inner_point(rVD);
1034 s[i].D = rVD;
1036 if (nvar == 1) {
1037 s[i].E = summate_over_1d_pdomain(e, PP, PD, inner->p+1, options);
1038 } else if (nvar == 2) {
1039 summator_2d s2d(e, PP, inner->p+1, rVD->Dimension);
1041 s[i].E = s2d.summate_over_pdomain(PP, facets, PD, options);
1044 Vector_Free(inner);
1045 free(facets);
1046 END_FORALL_REDUCED_DOMAIN
1047 Polyhedron_Free(TC);
1048 Polyhedron_Free(U);
1049 Param_Polyhedron_Free(PP);
1051 options->MaxRays = MaxRays;
1053 res = evalue_from_section_array(s, nd);
1054 free(s);
1056 return res;
1059 evalue *euler_summate(evalue *e, unsigned nvar,
1060 struct barvinok_options *options)
1062 int i;
1063 evalue *res;
1065 assert(nvar <= 2);
1067 assert(nvar >= 0);
1068 if (nvar == 0 || EVALUE_IS_ZERO(*e))
1069 return evalue_dup(e);
1071 assert(value_zero_p(e->d));
1072 assert(e->x.p->type == partition);
1074 res = evalue_zero();
1076 for (i = 0; i < e->x.p->size/2; ++i) {
1077 evalue *t;
1078 t = summate_over_domain(&e->x.p->arr[2*i+1], nvar,
1079 EVALUE_DOMAIN(e->x.p->arr[2*i]), options);
1080 eadd(t, res);
1081 evalue_free(t);
1084 return res;