Add Laurent expansion based summation
[barvinok.git] / barvinok.cc
blobef308b4c88f385a158261c773a2220c759f8a525
1 #include <assert.h>
2 #include <iostream>
3 #include <vector>
4 #include <deque>
5 #include <string>
6 #include <sstream>
7 #include <gmp.h>
8 #include <NTL/mat_ZZ.h>
9 #include <NTL/LLL.h>
10 #include <barvinok/util.h>
11 #include <barvinok/evalue.h>
12 #include "config.h"
13 #include <barvinok/barvinok.h>
14 #include <barvinok/genfun.h>
15 #include <barvinok/options.h>
16 #include <barvinok/sample.h>
17 #include "bfcounter.h"
18 #include "conversion.h"
19 #include "counter.h"
20 #include "decomposer.h"
21 #include "euler.h"
22 #include "lattice_point.h"
23 #include "laurent.h"
24 #include "reduce_domain.h"
25 #include "remove_equalities.h"
26 #include "scale.h"
27 #include "volume.h"
28 #include "bernoulli.h"
29 #include "param_util.h"
31 #ifdef NTL_STD_CXX
32 using namespace NTL;
33 #endif
34 using std::cerr;
35 using std::cout;
36 using std::endl;
37 using std::vector;
38 using std::deque;
39 using std::string;
40 using std::ostringstream;
42 #define ALLOC(t,p) p = (t*)malloc(sizeof(*p))
44 static evalue *barvinok_summate_unweighted(Polyhedron *P, Polyhedron *C,
45 evalue *(*summate)(evalue *, unsigned, struct barvinok_options *options),
46 struct barvinok_options *options);
48 class dpoly_n {
49 public:
50 Matrix *coeff;
51 ~dpoly_n() {
52 Matrix_Free(coeff);
54 dpoly_n(int d) {
55 Value d0, one;
56 value_init(d0);
57 value_init(one);
58 value_set_si(one, 1);
59 coeff = Matrix_Alloc(d+1, d+1+1);
60 value_set_si(coeff->p[0][0], 1);
61 value_set_si(coeff->p[0][d+1], 1);
62 for (int i = 1; i <= d; ++i) {
63 value_multiply(coeff->p[i][0], coeff->p[i-1][0], d0);
64 Vector_Combine(coeff->p[i-1], coeff->p[i-1]+1, coeff->p[i]+1,
65 one, d0, i);
66 value_set_si(coeff->p[i][d+1], i);
67 value_multiply(coeff->p[i][d+1], coeff->p[i][d+1], coeff->p[i-1][d+1]);
68 value_decrement(d0, d0);
70 value_clear(d0);
71 value_clear(one);
73 void div(dpoly& d, Vector *count, int sign) {
74 int len = coeff->NbRows;
75 Matrix * c = Matrix_Alloc(coeff->NbRows, coeff->NbColumns);
76 Value tmp;
77 value_init(tmp);
78 for (int i = 0; i < len; ++i) {
79 Vector_Copy(coeff->p[i], c->p[i], len+1);
80 for (int j = 1; j <= i; ++j) {
81 value_multiply(tmp, d.coeff->p[j], c->p[i][len]);
82 value_oppose(tmp, tmp);
83 Vector_Combine(c->p[i], c->p[i-j], c->p[i],
84 c->p[i-j][len], tmp, len);
85 value_multiply(c->p[i][len], c->p[i][len], c->p[i-j][len]);
87 value_multiply(c->p[i][len], c->p[i][len], d.coeff->p[0]);
89 if (sign == -1) {
90 value_set_si(tmp, -1);
91 Vector_Scale(c->p[len-1], count->p, tmp, len);
92 value_assign(count->p[len], c->p[len-1][len]);
93 } else
94 Vector_Copy(c->p[len-1], count->p, len+1);
95 Vector_Normalize(count->p, len+1);
96 value_clear(tmp);
97 Matrix_Free(c);
101 const int MAX_TRY=10;
103 * Searches for a vector that is not orthogonal to any
104 * of the rays in rays.
106 static void nonorthog(mat_ZZ& rays, vec_ZZ& lambda)
108 int dim = rays.NumCols();
109 bool found = false;
110 lambda.SetLength(dim);
111 if (dim == 0)
112 return;
114 for (int i = 2; !found && i <= 50*dim; i+=4) {
115 for (int j = 0; j < MAX_TRY; ++j) {
116 for (int k = 0; k < dim; ++k) {
117 int r = random_int(i)+2;
118 int v = (2*(r%2)-1) * (r >> 1);
119 lambda[k] = v;
121 int k = 0;
122 for (; k < rays.NumRows(); ++k)
123 if (lambda * rays[k] == 0)
124 break;
125 if (k == rays.NumRows()) {
126 found = true;
127 break;
131 assert(found);
134 static void add_rays(mat_ZZ& rays, Polyhedron *i, int *r, int nvar = -1,
135 bool all = false)
137 unsigned dim = i->Dimension;
138 if (nvar == -1)
139 nvar = dim;
140 for (int k = 0; k < i->NbRays; ++k) {
141 if (!value_zero_p(i->Ray[k][dim+1]))
142 continue;
143 if (!all && nvar != dim && First_Non_Zero(i->Ray[k]+1, nvar) == -1)
144 continue;
145 values2zz(i->Ray[k]+1, rays[(*r)++], nvar);
149 struct bfe_term : public bfc_term_base {
150 vector<evalue *> factors;
152 bfe_term(int len) : bfc_term_base(len) {
155 ~bfe_term() {
156 for (int i = 0; i < factors.size(); ++i) {
157 if (!factors[i])
158 continue;
159 free_evalue_refs(factors[i]);
160 delete factors[i];
165 static void print_int_vector(int *v, int len, const char *name)
167 cerr << name << endl;
168 for (int j = 0; j < len; ++j) {
169 cerr << v[j] << " ";
171 cerr << endl;
174 static void print_bfc_terms(mat_ZZ& factors, bfc_vec& v)
176 cerr << endl;
177 cerr << "factors" << endl;
178 cerr << factors << endl;
179 for (int i = 0; i < v.size(); ++i) {
180 cerr << "term: " << i << endl;
181 print_int_vector(v[i]->powers, factors.NumRows(), "powers");
182 cerr << "terms" << endl;
183 cerr << v[i]->terms << endl;
184 bfc_term* bfct = static_cast<bfc_term *>(v[i]);
185 cerr << bfct->c << endl;
189 static void print_bfe_terms(mat_ZZ& factors, bfc_vec& v)
191 cerr << endl;
192 cerr << "factors" << endl;
193 cerr << factors << endl;
194 for (int i = 0; i < v.size(); ++i) {
195 cerr << "term: " << i << endl;
196 print_int_vector(v[i]->powers, factors.NumRows(), "powers");
197 cerr << "terms" << endl;
198 cerr << v[i]->terms << endl;
199 bfe_term* bfet = static_cast<bfe_term *>(v[i]);
200 for (int j = 0; j < v[i]->terms.NumRows(); ++j) {
201 const char * test[] = {"a", "b"};
202 print_evalue(stderr, bfet->factors[j], test);
203 fprintf(stderr, "\n");
208 struct bfcounter : public bfcounter_base {
209 mpq_t count;
210 Value tz;
212 bfcounter(unsigned dim) : bfcounter_base(dim) {
213 mpq_init(count);
214 lower = 1;
215 value_init(tz);
217 ~bfcounter() {
218 mpq_clear(count);
219 value_clear(tz);
221 virtual void base(mat_ZZ& factors, bfc_vec& v);
222 virtual void get_count(Value *result) {
223 assert(value_one_p(&count[0]._mp_den));
224 value_assign(*result, &count[0]._mp_num);
228 void bfcounter::base(mat_ZZ& factors, bfc_vec& v)
230 unsigned nf = factors.NumRows();
232 for (int i = 0; i < v.size(); ++i) {
233 bfc_term* bfct = static_cast<bfc_term *>(v[i]);
234 int total_power = 0;
235 // factor is always positive, so we always
236 // change signs
237 for (int k = 0; k < nf; ++k)
238 total_power += v[i]->powers[k];
240 int j;
241 for (j = 0; j < nf; ++j)
242 if (v[i]->powers[j] > 0)
243 break;
245 zz2value(factors[j][0], tz);
246 dpoly D(total_power, tz, 1);
247 for (int k = 1; k < v[i]->powers[j]; ++k) {
248 zz2value(factors[j][0], tz);
249 dpoly fact(total_power, tz, 1);
250 D *= fact;
252 for ( ; ++j < nf; )
253 for (int k = 0; k < v[i]->powers[j]; ++k) {
254 zz2value(factors[j][0], tz);
255 dpoly fact(total_power, tz, 1);
256 D *= fact;
259 for (int k = 0; k < v[i]->terms.NumRows(); ++k) {
260 zz2value(v[i]->terms[k][0], tz);
261 dpoly n(total_power, tz);
262 mpq_set_si(tcount, 0, 1);
263 n.div(D, tcount, 1);
264 if (total_power % 2)
265 bfct->c[k].n = -bfct->c[k].n;
266 zz2value(bfct->c[k].n, tn);
267 zz2value(bfct->c[k].d, td);
269 mpz_mul(mpq_numref(tcount), mpq_numref(tcount), tn);
270 mpz_mul(mpq_denref(tcount), mpq_denref(tcount), td);
271 mpq_canonicalize(tcount);
272 mpq_add(count, count, tcount);
274 delete v[i];
279 /* Check whether the polyhedron is unbounded and if so,
280 * check whether it has any (and therefore an infinite number of)
281 * integer points.
282 * If one of the vertices is integer, then we are done.
283 * Otherwise, transform the polyhedron such that one of the rays
284 * is the first unit vector and cut it off at a height that ensures
285 * that if the whole polyhedron has any points, then the remaining part
286 * has integer points. In particular we add the largest coefficient
287 * of a ray to the highest vertex (rounded up).
289 static bool Polyhedron_is_infinite(Polyhedron *P, Value* result,
290 barvinok_options *options)
292 int r = 0;
293 Matrix *M, *M2;
294 Value c, tmp;
295 Value g;
296 bool first;
297 Vector *v;
298 Value offset, size;
299 Polyhedron *R;
301 if (P->NbBid == 0)
302 for (; r < P->NbRays; ++r)
303 if (value_zero_p(P->Ray[r][P->Dimension+1]))
304 break;
305 if (P->NbBid == 0 && r == P->NbRays)
306 return false;
308 if (options->count_sample_infinite) {
309 Vector *sample;
311 sample = Polyhedron_Sample(P, options);
312 if (!sample)
313 value_set_si(*result, 0);
314 else {
315 value_set_si(*result, -1);
316 Vector_Free(sample);
318 return true;
321 for (int i = 0; i < P->NbRays; ++i)
322 if (value_one_p(P->Ray[i][1+P->Dimension])) {
323 value_set_si(*result, -1);
324 return true;
327 value_init(g);
328 M = Matrix_Alloc(P->Dimension+1, P->Dimension+1);
329 Vector_Gcd(P->Ray[r]+1, P->Dimension, &g);
330 Vector_AntiScale(P->Ray[r]+1, M->p[0], g, P->Dimension+1);
331 int ok = unimodular_complete(M, 1);
332 assert(ok);
333 value_set_si(M->p[P->Dimension][P->Dimension], 1);
334 M2 = Transpose(M);
335 Matrix_Free(M);
336 P = Polyhedron_Preimage(P, M2, 0);
337 Matrix_Free(M2);
338 value_clear(g);
340 first = true;
341 value_init(offset);
342 value_init(size);
343 value_init(tmp);
344 value_set_si(size, 0);
346 for (int i = 0; i < P->NbBid; ++i) {
347 value_absolute(tmp, P->Ray[i][1]);
348 if (value_gt(tmp, size))
349 value_assign(size, tmp);
351 for (int i = P->NbBid; i < P->NbRays; ++i) {
352 if (value_zero_p(P->Ray[i][P->Dimension+1])) {
353 if (value_gt(P->Ray[i][1], size))
354 value_assign(size, P->Ray[i][1]);
355 continue;
357 mpz_cdiv_q(tmp, P->Ray[i][1], P->Ray[i][P->Dimension+1]);
358 if (first || value_gt(tmp, offset)) {
359 value_assign(offset, tmp);
360 first = false;
363 value_addto(offset, offset, size);
364 value_clear(size);
365 value_clear(tmp);
367 v = Vector_Alloc(P->Dimension+2);
368 value_set_si(v->p[0], 1);
369 value_set_si(v->p[1], -1);
370 value_assign(v->p[1+P->Dimension], offset);
371 R = AddConstraints(v->p, 1, P, options->MaxRays);
372 Polyhedron_Free(P);
373 P = R;
375 value_clear(offset);
376 Vector_Free(v);
378 value_init(c);
379 barvinok_count_with_options(P, &c, options);
380 Polyhedron_Free(P);
381 if (value_zero_p(c))
382 value_set_si(*result, 0);
383 else
384 value_set_si(*result, -1);
385 value_clear(c);
387 return true;
390 static void evalue2value(evalue *e, Value *v)
392 if (EVALUE_IS_ZERO(*e)) {
393 value_set_si(*v, 0);
394 return;
397 if (value_notzero_p(e->d)) {
398 assert(value_one_p(e->d));
399 value_assign(*v, e->x.n);
400 return;
403 assert(e->x.p->type == partition);
404 assert(e->x.p->size == 2);
405 assert(EVALUE_DOMAIN(e->x.p->arr[0])->Dimension == 0);
406 evalue2value(&e->x.p->arr[1], v);
409 static void barvinok_count_f(Polyhedron *P, Value* result,
410 barvinok_options *options);
412 void barvinok_count_with_options(Polyhedron *P, Value* result,
413 struct barvinok_options *options)
415 unsigned dim;
416 int allocated = 0;
417 Polyhedron *Q;
418 bool infinite = false;
420 if (P->next)
421 fprintf(stderr,
422 "barvinok_count: input is a union; only first polyhedron is counted\n");
424 if (emptyQ2(P)) {
425 value_set_si(*result, 0);
426 return;
428 if (P->NbEq != 0) {
429 Q = NULL;
430 do {
431 P = remove_equalities(P, options->MaxRays);
432 P = DomainConstraintSimplify(P, options->MaxRays);
433 if (Q)
434 Polyhedron_Free(Q);
435 Q = P;
436 } while (!emptyQ(P) && P->NbEq != 0);
437 if (emptyQ(P)) {
438 Polyhedron_Free(P);
439 value_set_si(*result, 0);
440 return;
442 allocated = 1;
444 if (Polyhedron_is_infinite(P, result, options)) {
445 if (allocated)
446 Polyhedron_Free(P);
447 return;
449 if (P->Dimension == 0) {
450 /* Test whether the constraints are satisfied */
451 POL_ENSURE_VERTICES(P);
452 value_set_si(*result, !emptyQ(P));
453 if (allocated)
454 Polyhedron_Free(P);
455 return;
457 if (options->summation == BV_SUM_BERNOULLI) {
458 Polyhedron *C = Universe_Polyhedron(0);
459 evalue *sum = barvinok_summate_unweighted(P, C, Bernoulli_sum_evalue,
460 options);
461 Polyhedron_Free(C);
462 evalue2value(sum, result);
463 evalue_free(sum);
464 return;
466 Q = Polyhedron_Factor(P, 0, NULL, options->MaxRays);
467 if (Q) {
468 if (allocated)
469 Polyhedron_Free(P);
470 P = Q;
471 allocated = 1;
474 barvinok_count_f(P, result, options);
475 if (value_neg_p(*result))
476 infinite = true;
477 if (Q && P->next && value_notzero_p(*result)) {
478 Value factor;
479 value_init(factor);
481 for (Q = P->next; Q; Q = Q->next) {
482 barvinok_count_f(Q, &factor, options);
483 if (value_neg_p(factor)) {
484 infinite = true;
485 continue;
486 } else if (Q->next && value_zero_p(factor)) {
487 value_set_si(*result, 0);
488 break;
490 value_multiply(*result, *result, factor);
493 value_clear(factor);
496 if (allocated)
497 Domain_Free(P);
498 if (infinite)
499 value_set_si(*result, -1);
502 void barvinok_count(Polyhedron *P, Value* result, unsigned NbMaxCons)
504 barvinok_options *options = barvinok_options_new_with_defaults();
505 options->MaxRays = NbMaxCons;
506 barvinok_count_with_options(P, result, options);
507 barvinok_options_free(options);
510 static void barvinok_count_f(Polyhedron *P, Value* result,
511 barvinok_options *options)
513 if (emptyQ2(P)) {
514 value_set_si(*result, 0);
515 return;
518 if (P->Dimension == 1)
519 return Line_Length(P, result);
521 int c = P->NbConstraints;
522 POL_ENSURE_FACETS(P);
523 if (c != P->NbConstraints || P->NbEq != 0) {
524 Polyhedron *next = P->next;
525 P->next = NULL;
526 barvinok_count_with_options(P, result, options);
527 P->next = next;
528 return;
531 POL_ENSURE_VERTICES(P);
533 if (Polyhedron_is_infinite(P, result, options))
534 return;
536 np_base *cnt;
537 if (options->incremental_specialization == BV_SPECIALIZATION_BF)
538 cnt = new bfcounter(P->Dimension);
539 else if (options->incremental_specialization == BV_SPECIALIZATION_DF)
540 cnt = new icounter(P->Dimension);
541 else if (options->incremental_specialization == BV_SPECIALIZATION_TODD)
542 cnt = new tcounter(P->Dimension, options->max_index);
543 else
544 cnt = new counter(P->Dimension, options->max_index);
545 cnt->start(P, options);
547 cnt->get_count(result);
548 delete cnt;
551 static void uni_polynom(int param, Vector *c, evalue *EP)
553 unsigned dim = c->Size-2;
554 value_init(EP->d);
555 value_set_si(EP->d,0);
556 EP->x.p = new_enode(polynomial, dim+1, param+1);
557 for (int j = 0; j <= dim; ++j)
558 evalue_set(&EP->x.p->arr[j], c->p[j], c->p[dim+1]);
561 typedef evalue * evalue_p;
563 struct enumerator_base {
564 unsigned dim;
565 evalue ** vE;
566 evalue mone;
567 vertex_decomposer *vpd;
569 enumerator_base(unsigned dim, vertex_decomposer *vpd)
571 this->dim = dim;
572 this->vpd = vpd;
574 vE = new evalue_p[vpd->PP->nbV];
575 for (int j = 0; j < vpd->PP->nbV; ++j)
576 vE[j] = 0;
578 value_init(mone.d);
579 evalue_set_si(&mone, -1, 1);
582 void decompose_at(Param_Vertices *V, int _i, barvinok_options *options) {
583 //this->pVD = pVD;
585 vE[_i] = new evalue;
586 value_init(vE[_i]->d);
587 evalue_set_si(vE[_i], 0, 1);
589 vpd->decompose_at_vertex(V, _i, options);
592 virtual ~enumerator_base() {
593 for (int j = 0; j < vpd->PP->nbV; ++j)
594 if (vE[j]) {
595 free_evalue_refs(vE[j]);
596 delete vE[j];
598 delete [] vE;
600 free_evalue_refs(&mone);
603 static enumerator_base *create(Polyhedron *P, unsigned dim,
604 Param_Polyhedron *PP,
605 barvinok_options *options);
608 struct enumerator : public signed_cone_consumer, public vertex_decomposer,
609 public enumerator_base {
610 vec_ZZ lambda;
611 vec_ZZ den;
612 term_info num;
613 Vector *c;
614 mpq_t count;
615 Value tz;
617 enumerator(Polyhedron *P, unsigned dim, Param_Polyhedron *PP) :
618 vertex_decomposer(PP, *this), enumerator_base(dim, this) {
619 randomvector(P, lambda, dim);
620 den.SetLength(dim);
621 c = Vector_Alloc(dim+2);
623 mpq_init(count);
624 value_init(tz);
627 ~enumerator() {
628 mpq_clear(count);
629 Vector_Free(c);
630 value_clear(tz);
633 virtual void handle(const signed_cone& sc, barvinok_options *options);
636 void enumerator::handle(const signed_cone& sc, barvinok_options *options)
638 int sign = sc.sign;
639 int r = 0;
640 assert(sc.rays.NumRows() == dim);
641 for (int k = 0; k < dim; ++k) {
642 if (lambda * sc.rays[k] == 0)
643 throw Orthogonal;
646 lattice_point(V, sc.rays, lambda, &num, sc.det, options);
647 den = sc.rays * lambda;
649 if (dim % 2)
650 sign = -sign;
652 zz2value(den[0], tz);
653 dpoly n(dim, tz, 1);
654 for (int k = 1; k < dim; ++k) {
655 zz2value(den[k], tz);
656 dpoly fact(dim, tz, 1);
657 n *= fact;
659 if (num.E != NULL) {
660 dpoly_n d(dim);
661 d.div(n, c, sign);
662 for (unsigned long i = 0; i < sc.det; ++i) {
663 evalue *EV = evalue_polynomial(c, num.E[i]);
664 eadd(EV, vE[vert]);
665 evalue_free(EV);
666 free_evalue_refs(num.E[i]);
667 delete num.E[i];
669 delete [] num.E;
670 } else {
671 mpq_set_si(count, 0, 1);
672 if (num.constant.length() == 1) {
673 zz2value(num.constant[0], tz);
674 dpoly d(dim, tz);
675 d.div(n, count, sign);
676 } else {
677 dpoly_n d(dim);
678 d.div(n, c, sign);
679 Value x, sum, acc;
680 value_init(x);
681 value_init(acc);
682 for (unsigned long i = 0; i < sc.det; ++i) {
683 value_assign(acc, c->p[dim]);
684 zz2value(num.constant[i], x);
685 for (int j = dim-1; j >= 0; --j) {
686 value_multiply(acc, acc, x);
687 value_addto(acc, acc, c->p[j]);
689 value_addto(mpq_numref(count), mpq_numref(count), acc);
691 mpz_set(mpq_denref(count), c->p[dim+1]);
692 value_clear(acc);
693 value_clear(x);
695 evalue EV;
696 value_init(EV.d);
697 evalue_set(&EV, &count[0]._mp_num, &count[0]._mp_den);
698 eadd(&EV, vE[vert]);
699 free_evalue_refs(&EV);
703 struct ienumerator_base : enumerator_base {
704 evalue ** E_vertex;
706 ienumerator_base(unsigned dim, vertex_decomposer *vpd) :
707 enumerator_base(dim,vpd) {
708 E_vertex = new evalue_p[dim];
711 virtual ~ienumerator_base() {
712 delete [] E_vertex;
715 evalue *E_num(int i, int d) {
716 return E_vertex[i + (dim-d)];
720 struct cumulator {
721 evalue *factor;
722 evalue *v;
723 dpoly_r *r;
725 cumulator(evalue *factor, evalue *v, dpoly_r *r) :
726 factor(factor), v(v), r(r) {}
728 void cumulate(barvinok_options *options);
730 virtual void add_term(const vector<int>& powers, evalue *f2) = 0;
731 virtual ~cumulator() {}
734 void cumulator::cumulate(barvinok_options *options)
736 evalue cum; // factor * 1 * E_num[0]/1 * (E_num[0]-1)/2 *...
737 evalue f;
738 evalue t; // E_num[0] - (m-1)
739 evalue *cst;
740 evalue mone;
742 if (options->lookup_table) {
743 value_init(mone.d);
744 evalue_set_si(&mone, -1, 1);
747 value_init(cum.d);
748 evalue_copy(&cum, factor);
749 value_init(f.d);
750 value_init(f.x.n);
751 value_set_si(f.d, 1);
752 value_set_si(f.x.n, 1);
753 value_init(t.d);
754 evalue_copy(&t, v);
756 if (!options->lookup_table) {
757 for (cst = &t; value_zero_p(cst->d); ) {
758 if (cst->x.p->type == fractional)
759 cst = &cst->x.p->arr[1];
760 else
761 cst = &cst->x.p->arr[0];
765 for (int m = 0; m < r->len; ++m) {
766 if (m > 0) {
767 if (m > 1) {
768 value_set_si(f.d, m);
769 emul(&f, &cum);
770 if (!options->lookup_table)
771 value_subtract(cst->x.n, cst->x.n, cst->d);
772 else
773 eadd(&mone, &t);
775 emul(&t, &cum);
777 dpoly_r_term_list& current = r->c[r->len-1-m];
778 dpoly_r_term_list::iterator j;
779 for (j = current.begin(); j != current.end(); ++j) {
780 if ((*j)->coeff == 0)
781 continue;
782 evalue *f2 = new evalue;
783 value_init(f2->d);
784 value_init(f2->x.n);
785 zz2value((*j)->coeff, f2->x.n);
786 zz2value(r->denom, f2->d);
787 emul(&cum, f2);
789 add_term((*j)->powers, f2);
792 free_evalue_refs(&f);
793 free_evalue_refs(&t);
794 free_evalue_refs(&cum);
795 if (options->lookup_table)
796 free_evalue_refs(&mone);
799 struct E_poly_term {
800 vector<int> powers;
801 evalue *E;
804 struct ie_cum : public cumulator {
805 vector<E_poly_term *> terms;
807 ie_cum(evalue *factor, evalue *v, dpoly_r *r) : cumulator(factor, v, r) {}
809 virtual void add_term(const vector<int>& powers, evalue *f2);
812 void ie_cum::add_term(const vector<int>& powers, evalue *f2)
814 int k;
815 for (k = 0; k < terms.size(); ++k) {
816 if (terms[k]->powers == powers) {
817 eadd(f2, terms[k]->E);
818 free_evalue_refs(f2);
819 delete f2;
820 break;
823 if (k >= terms.size()) {
824 E_poly_term *ET = new E_poly_term;
825 ET->powers = powers;
826 ET->E = f2;
827 terms.push_back(ET);
831 struct ienumerator : public signed_cone_consumer, public vertex_decomposer,
832 public ienumerator_base {
833 //Polyhedron *pVD;
834 mat_ZZ den;
835 mat_ZZ vertex;
836 mpq_t tcount;
837 Value tz;
839 ienumerator(Polyhedron *P, unsigned dim, Param_Polyhedron *PP) :
840 vertex_decomposer(PP, *this), ienumerator_base(dim, this) {
841 vertex.SetDims(1, dim);
843 den.SetDims(dim, dim);
844 mpq_init(tcount);
845 value_init(tz);
848 ~ienumerator() {
849 mpq_clear(tcount);
850 value_clear(tz);
853 virtual void handle(const signed_cone& sc, barvinok_options *options);
854 void reduce(evalue *factor, const mat_ZZ& num, const mat_ZZ& den_f,
855 barvinok_options *options);
858 void ienumerator::reduce(evalue *factor, const mat_ZZ& num, const mat_ZZ& den_f,
859 barvinok_options *options)
861 unsigned len = den_f.NumRows(); // number of factors in den
862 unsigned dim = num.NumCols();
863 assert(num.NumRows() == 1);
865 if (dim == 0) {
866 eadd(factor, vE[vert]);
867 return;
870 vec_ZZ den_s;
871 mat_ZZ den_r;
872 vec_ZZ num_s;
873 mat_ZZ num_p;
875 split_one(num, num_s, num_p, den_f, den_s, den_r);
877 vec_ZZ den_p;
878 den_p.SetLength(len);
880 ZZ one;
881 one = 1;
882 normalize(one, num_s, num_p, den_s, den_p, den_r);
883 if (one != 1)
884 emul(&mone, factor);
886 int only_param = 0;
887 int no_param = 0;
888 for (int k = 0; k < len; ++k) {
889 if (den_p[k] == 0)
890 ++no_param;
891 else if (den_s[k] == 0)
892 ++only_param;
894 if (no_param == 0) {
895 reduce(factor, num_p, den_r, options);
896 } else {
897 int k, l;
898 mat_ZZ pden;
899 pden.SetDims(only_param, dim-1);
901 for (k = 0, l = 0; k < len; ++k)
902 if (den_s[k] == 0)
903 pden[l++] = den_r[k];
905 for (k = 0; k < len; ++k)
906 if (den_p[k] == 0)
907 break;
909 zz2value(num_s[0], tz);
910 dpoly n(no_param, tz);
911 zz2value(den_s[k], tz);
912 dpoly D(no_param, tz, 1);
913 for ( ; ++k < len; )
914 if (den_p[k] == 0) {
915 zz2value(den_s[k], tz);
916 dpoly fact(no_param, tz, 1);
917 D *= fact;
920 dpoly_r * r = 0;
921 // if no_param + only_param == len then all powers
922 // below will be all zero
923 if (no_param + only_param == len) {
924 if (E_num(0, dim) != 0)
925 r = new dpoly_r(n, len);
926 else {
927 mpq_set_si(tcount, 0, 1);
928 one = 1;
929 n.div(D, tcount, 1);
931 if (value_notzero_p(mpq_numref(tcount))) {
932 evalue f;
933 value_init(f.d);
934 value_init(f.x.n);
935 value_assign(f.x.n, mpq_numref(tcount));
936 value_assign(f.d, mpq_denref(tcount));
937 emul(&f, factor);
938 reduce(factor, num_p, pden, options);
939 free_evalue_refs(&f);
941 return;
943 } else {
944 for (k = 0; k < len; ++k) {
945 if (den_s[k] == 0 || den_p[k] == 0)
946 continue;
948 zz2value(den_s[k], tz);
949 dpoly pd(no_param-1, tz, 1);
951 int l;
952 for (l = 0; l < k; ++l)
953 if (den_r[l] == den_r[k])
954 break;
956 if (r == 0)
957 r = new dpoly_r(n, pd, l, len);
958 else {
959 dpoly_r *nr = new dpoly_r(r, pd, l, len);
960 delete r;
961 r = nr;
965 dpoly_r *rc = r->div(D);
966 delete r;
967 r = rc;
968 if (E_num(0, dim) == 0) {
969 int common = pden.NumRows();
970 dpoly_r_term_list& final = r->c[r->len-1];
971 int rows;
972 evalue t;
973 evalue f;
974 value_init(f.d);
975 value_init(f.x.n);
976 zz2value(r->denom, f.d);
977 dpoly_r_term_list::iterator j;
978 for (j = final.begin(); j != final.end(); ++j) {
979 if ((*j)->coeff == 0)
980 continue;
981 rows = common;
982 for (int k = 0; k < r->dim; ++k) {
983 int n = (*j)->powers[k];
984 if (n == 0)
985 continue;
986 pden.SetDims(rows+n, pden.NumCols());
987 for (int l = 0; l < n; ++l)
988 pden[rows+l] = den_r[k];
989 rows += n;
991 value_init(t.d);
992 evalue_copy(&t, factor);
993 zz2value((*j)->coeff, f.x.n);
994 emul(&f, &t);
995 reduce(&t, num_p, pden, options);
996 free_evalue_refs(&t);
998 free_evalue_refs(&f);
999 } else {
1000 ie_cum cum(factor, E_num(0, dim), r);
1001 cum.cumulate(options);
1003 int common = pden.NumRows();
1004 int rows;
1005 for (int j = 0; j < cum.terms.size(); ++j) {
1006 rows = common;
1007 pden.SetDims(rows, pden.NumCols());
1008 for (int k = 0; k < r->dim; ++k) {
1009 int n = cum.terms[j]->powers[k];
1010 if (n == 0)
1011 continue;
1012 pden.SetDims(rows+n, pden.NumCols());
1013 for (int l = 0; l < n; ++l)
1014 pden[rows+l] = den_r[k];
1015 rows += n;
1017 reduce(cum.terms[j]->E, num_p, pden, options);
1018 free_evalue_refs(cum.terms[j]->E);
1019 delete cum.terms[j]->E;
1020 delete cum.terms[j];
1023 delete r;
1027 static int type_offset(enode *p)
1029 return p->type == fractional ? 1 :
1030 p->type == flooring ? 1 : 0;
1033 static int edegree(evalue *e)
1035 int d = 0;
1036 enode *p;
1038 if (value_notzero_p(e->d))
1039 return 0;
1041 p = e->x.p;
1042 int i = type_offset(p);
1043 if (p->size-i-1 > d)
1044 d = p->size - i - 1;
1045 for (; i < p->size; i++) {
1046 int d2 = edegree(&p->arr[i]);
1047 if (d2 > d)
1048 d = d2;
1050 return d;
1053 void ienumerator::handle(const signed_cone& sc, barvinok_options *options)
1055 assert(sc.det == 1);
1056 assert(sc.rays.NumRows() == dim);
1058 lattice_point(V, sc.rays, vertex[0], E_vertex, options);
1060 den = sc.rays;
1062 evalue one;
1063 value_init(one.d);
1064 evalue_set_si(&one, sc.sign, 1);
1065 reduce(&one, vertex, den, options);
1066 free_evalue_refs(&one);
1068 for (int i = 0; i < dim; ++i)
1069 if (E_vertex[i])
1070 evalue_free(E_vertex[i]);
1073 struct bfenumerator : public vertex_decomposer, public bf_base,
1074 public ienumerator_base {
1075 evalue *factor;
1077 bfenumerator(Polyhedron *P, unsigned dim, Param_Polyhedron *PP) :
1078 vertex_decomposer(PP, *this),
1079 bf_base(dim), ienumerator_base(dim, this) {
1080 lower = 0;
1081 factor = NULL;
1084 ~bfenumerator() {
1087 virtual void handle(const signed_cone& sc, barvinok_options *options);
1088 virtual void base(mat_ZZ& factors, bfc_vec& v);
1090 bfc_term_base* new_bf_term(int len) {
1091 bfe_term* t = new bfe_term(len);
1092 return t;
1095 virtual void set_factor(bfc_term_base *t, int k, int change) {
1096 bfe_term* bfet = static_cast<bfe_term *>(t);
1097 factor = bfet->factors[k];
1098 assert(factor != NULL);
1099 bfet->factors[k] = NULL;
1100 if (change)
1101 emul(&mone, factor);
1104 virtual void set_factor(bfc_term_base *t, int k, mpq_t &q, int change) {
1105 bfe_term* bfet = static_cast<bfe_term *>(t);
1106 factor = bfet->factors[k];
1107 assert(factor != NULL);
1108 bfet->factors[k] = NULL;
1110 evalue f;
1111 value_init(f.d);
1112 value_init(f.x.n);
1113 if (change)
1114 value_oppose(f.x.n, mpq_numref(q));
1115 else
1116 value_assign(f.x.n, mpq_numref(q));
1117 value_assign(f.d, mpq_denref(q));
1118 emul(&f, factor);
1119 free_evalue_refs(&f);
1122 virtual void set_factor(bfc_term_base *t, int k, const QQ& c, int change) {
1123 bfe_term* bfet = static_cast<bfe_term *>(t);
1125 factor = new evalue;
1127 evalue f;
1128 value_init(f.d);
1129 value_init(f.x.n);
1130 zz2value(c.n, f.x.n);
1131 if (change)
1132 value_oppose(f.x.n, f.x.n);
1133 zz2value(c.d, f.d);
1135 value_init(factor->d);
1136 evalue_copy(factor, bfet->factors[k]);
1137 emul(&f, factor);
1138 free_evalue_refs(&f);
1141 void set_factor(evalue *f, int change) {
1142 if (change)
1143 emul(&mone, f);
1144 factor = f;
1147 virtual void insert_term(bfc_term_base *t, int i) {
1148 bfe_term* bfet = static_cast<bfe_term *>(t);
1149 int len = t->terms.NumRows()-1; // already increased by one
1151 bfet->factors.resize(len+1);
1152 for (int j = len; j > i; --j) {
1153 bfet->factors[j] = bfet->factors[j-1];
1154 t->terms[j] = t->terms[j-1];
1156 bfet->factors[i] = factor;
1157 factor = NULL;
1160 virtual void update_term(bfc_term_base *t, int i) {
1161 bfe_term* bfet = static_cast<bfe_term *>(t);
1163 eadd(factor, bfet->factors[i]);
1164 free_evalue_refs(factor);
1165 delete factor;
1168 virtual bool constant_vertex(int dim) { return E_num(0, dim) == 0; }
1170 virtual void cum(bf_reducer *bfr, bfc_term_base *t, int k, dpoly_r *r,
1171 barvinok_options *options);
1174 enumerator_base *enumerator_base::create(Polyhedron *P, unsigned dim,
1175 Param_Polyhedron *PP,
1176 barvinok_options *options)
1178 enumerator_base *eb;
1180 if (options->incremental_specialization == BV_SPECIALIZATION_BF)
1181 eb = new bfenumerator(P, dim, PP);
1182 else if (options->incremental_specialization == BV_SPECIALIZATION_DF)
1183 eb = new ienumerator(P, dim, PP);
1184 else
1185 eb = new enumerator(P, dim, PP);
1187 return eb;
1190 struct bfe_cum : public cumulator {
1191 bfenumerator *bfe;
1192 bfc_term_base *told;
1193 int k;
1194 bf_reducer *bfr;
1196 bfe_cum(evalue *factor, evalue *v, dpoly_r *r, bf_reducer *bfr,
1197 bfc_term_base *t, int k, bfenumerator *e) :
1198 cumulator(factor, v, r), told(t), k(k),
1199 bfr(bfr), bfe(e) {
1202 virtual void add_term(const vector<int>& powers, evalue *f2);
1205 void bfe_cum::add_term(const vector<int>& powers, evalue *f2)
1207 bfr->update_powers(powers);
1209 bfc_term_base * t = bfe->find_bfc_term(bfr->vn, bfr->npowers, bfr->nnf);
1210 bfe->set_factor(f2, bfr->l_changes % 2);
1211 bfe->add_term(t, told->terms[k], bfr->l_extra_num);
1214 void bfenumerator::cum(bf_reducer *bfr, bfc_term_base *t, int k,
1215 dpoly_r *r, barvinok_options *options)
1217 bfe_term* bfet = static_cast<bfe_term *>(t);
1218 bfe_cum cum(bfet->factors[k], E_num(0, bfr->d), r, bfr, t, k, this);
1219 cum.cumulate(options);
1222 void bfenumerator::base(mat_ZZ& factors, bfc_vec& v)
1224 for (int i = 0; i < v.size(); ++i) {
1225 assert(v[i]->terms.NumRows() == 1);
1226 evalue *factor = static_cast<bfe_term *>(v[i])->factors[0];
1227 eadd(factor, vE[vert]);
1228 delete v[i];
1232 void bfenumerator::handle(const signed_cone& sc, barvinok_options *options)
1234 assert(sc.det == 1);
1235 assert(sc.rays.NumRows() == enumerator_base::dim);
1237 bfe_term* t = new bfe_term(enumerator_base::dim);
1238 vector< bfc_term_base * > v;
1239 v.push_back(t);
1241 t->factors.resize(1);
1243 t->terms.SetDims(1, enumerator_base::dim);
1244 lattice_point(V, sc.rays, t->terms[0], E_vertex, options);
1246 // the elements of factors are always lexpositive
1247 mat_ZZ factors;
1248 int s = setup_factors(sc.rays, factors, t, sc.sign);
1250 t->factors[0] = new evalue;
1251 value_init(t->factors[0]->d);
1252 evalue_set_si(t->factors[0], s, 1);
1253 reduce(factors, v, options);
1255 for (int i = 0; i < enumerator_base::dim; ++i)
1256 if (E_vertex[i])
1257 evalue_free(E_vertex[i]);
1260 static evalue* barvinok_enumerate_ev_f(Polyhedron *P, Polyhedron* C,
1261 barvinok_options *options);
1263 /* Destroys C */
1264 static evalue* barvinok_enumerate_cst(Polyhedron *P, Polyhedron* C,
1265 struct barvinok_options *options)
1267 evalue *eres;
1269 if (emptyQ2(C)) {
1270 Polyhedron_Free(C);
1271 return evalue_zero();
1274 ALLOC(evalue, eres);
1275 value_init(eres->d);
1276 value_set_si(eres->d, 0);
1277 eres->x.p = new_enode(partition, 2, C->Dimension);
1278 EVALUE_SET_DOMAIN(eres->x.p->arr[0],
1279 DomainConstraintSimplify(C, options->MaxRays));
1280 value_set_si(eres->x.p->arr[1].d, 1);
1281 value_init(eres->x.p->arr[1].x.n);
1282 if (emptyQ2(P))
1283 value_set_si(eres->x.p->arr[1].x.n, 0);
1284 else
1285 barvinok_count_with_options(P, &eres->x.p->arr[1].x.n, options);
1287 return eres;
1290 static evalue* enumerate(Polyhedron *P, Polyhedron* C,
1291 struct barvinok_options *options)
1293 Polyhedron *next;
1294 Polyhedron *Porig = P;
1295 Polyhedron *Corig = C;
1296 Polyhedron *CEq = NULL, *rVD;
1297 int r = 0;
1298 unsigned nparam = C->Dimension;
1299 evalue *eres;
1300 Matrix *CP = NULL;
1302 evalue factor;
1303 value_init(factor.d);
1304 evalue_set_si(&factor, 1, 1);
1306 /* for now */
1307 POL_ENSURE_FACETS(P);
1308 POL_ENSURE_VERTICES(P);
1309 POL_ENSURE_FACETS(C);
1310 POL_ENSURE_VERTICES(C);
1312 if (C->Dimension == 0 || emptyQ(P) || emptyQ(C)) {
1313 constant:
1314 if (CEq == Porig)
1315 CEq = Polyhedron_Copy(CEq);
1316 eres = barvinok_enumerate_cst(P, CEq ? CEq : Polyhedron_Copy(C), options);
1317 out:
1318 if (CP) {
1319 evalue_backsubstitute(eres, CP, options->MaxRays);
1320 Matrix_Free(CP);
1323 emul(&factor, eres);
1324 if (options->approximation_method == BV_APPROX_DROP) {
1325 if (options->polynomial_approximation == BV_APPROX_SIGN_UPPER)
1326 evalue_frac2polynomial(eres, 1, options->MaxRays);
1327 if (options->polynomial_approximation == BV_APPROX_SIGN_LOWER)
1328 evalue_frac2polynomial(eres, -1, options->MaxRays);
1329 if (options->polynomial_approximation == BV_APPROX_SIGN_APPROX)
1330 evalue_frac2polynomial(eres, 0, options->MaxRays);
1332 reduce_evalue(eres);
1333 free_evalue_refs(&factor);
1334 if (P != Porig)
1335 Domain_Free(P);
1336 if (C != Corig)
1337 Polyhedron_Free(C);
1339 return eres;
1341 if (Polyhedron_is_unbounded(P, nparam, options->MaxRays))
1342 goto constant;
1344 if (P->Dimension == nparam) {
1345 CEq = P;
1346 P = Universe_Polyhedron(0);
1347 goto constant;
1349 if (P->NbEq != 0 || C->NbEq != 0) {
1350 Polyhedron *Q = P;
1351 Polyhedron *D = C;
1352 remove_all_equalities(&P, &C, &CP, NULL, nparam, options->MaxRays);
1353 if (C != D && D != Corig)
1354 Polyhedron_Free(D);
1355 if (P != Q && Q != Porig)
1356 Domain_Free(Q);
1357 eres = enumerate(P, C, options);
1358 goto out;
1361 Polyhedron *T = Polyhedron_Factor(P, nparam, NULL, options->MaxRays);
1362 if (T || (P->Dimension == nparam+1)) {
1363 Polyhedron *Q;
1364 Polyhedron *C2;
1365 for (Q = T ? T : P; Q; Q = Q->next) {
1366 Polyhedron *next = Q->next;
1367 Q->next = NULL;
1369 Polyhedron *QC = Q;
1370 if (Q->Dimension != C->Dimension)
1371 QC = Polyhedron_Project(Q, nparam);
1373 C2 = C;
1374 C = DomainIntersection(C, QC, options->MaxRays);
1375 if (C2 != Corig)
1376 Polyhedron_Free(C2);
1377 if (QC != Q)
1378 Polyhedron_Free(QC);
1380 Q->next = next;
1383 if (T) {
1384 if (P != Porig)
1385 Polyhedron_Free(P);
1386 P = T;
1387 if (T->Dimension == C->Dimension) {
1388 P = T->next;
1389 T->next = NULL;
1390 Polyhedron_Free(T);
1394 next = P->next;
1395 P->next = NULL;
1396 eres = barvinok_enumerate_ev_f(P, C, options);
1397 P->next = next;
1399 if (P->next) {
1400 Polyhedron *Q;
1401 evalue *f;
1403 for (Q = P->next; Q; Q = Q->next) {
1404 Polyhedron *next = Q->next;
1405 Q->next = NULL;
1407 f = barvinok_enumerate_ev_f(Q, C, options);
1408 emul(f, eres);
1409 evalue_free(f);
1411 Q->next = next;
1415 goto out;
1418 evalue* barvinok_enumerate_with_options(Polyhedron *P, Polyhedron* C,
1419 struct barvinok_options *options)
1421 Polyhedron *next, *Cnext, *C1;
1422 Polyhedron *Corig = C;
1423 evalue *eres;
1425 if (P->next)
1426 fprintf(stderr,
1427 "barvinok_enumerate: input is a union; only first polyhedron is enumerated\n");
1429 if (C->next)
1430 fprintf(stderr,
1431 "barvinok_enumerate: context is a union; only first polyhedron is considered\n");
1433 Cnext = C->next;
1434 C->next = NULL;
1435 C1 = Polyhedron_Project(P, C->Dimension);
1436 C = DomainIntersection(C, C1, options->MaxRays);
1437 Polyhedron_Free(C1);
1438 next = P->next;
1439 P->next = NULL;
1441 if (options->approximation_method == BV_APPROX_BERNOULLI ||
1442 options->summation == BV_SUM_BERNOULLI)
1443 eres = barvinok_summate_unweighted(P, C, Bernoulli_sum_evalue, options);
1444 else
1445 eres = enumerate(P, C, options);
1446 Domain_Free(C);
1448 P->next= next;
1449 Corig->next = Cnext;
1451 return eres;
1454 evalue* barvinok_enumerate_ev(Polyhedron *P, Polyhedron* C, unsigned MaxRays)
1456 evalue *E;
1457 barvinok_options *options = barvinok_options_new_with_defaults();
1458 options->MaxRays = MaxRays;
1459 E = barvinok_enumerate_with_options(P, C, options);
1460 barvinok_options_free(options);
1461 return E;
1464 evalue *Param_Polyhedron_Enumerate(Param_Polyhedron *PP, Polyhedron *P,
1465 Polyhedron *C,
1466 struct barvinok_options *options)
1468 evalue *eres;
1469 Param_Domain *D;
1470 unsigned nparam = C->Dimension;
1471 unsigned dim = P->Dimension - nparam;
1473 int nd;
1474 for (nd = 0, D=PP->D; D; ++nd, D=D->next);
1475 evalue_section *s = new evalue_section[nd];
1477 enumerator_base *et = NULL;
1478 try_again:
1479 if (et)
1480 delete et;
1482 et = enumerator_base::create(P, dim, PP, options);
1484 Polyhedron *TC = true_context(P, C, options->MaxRays);
1485 FORALL_REDUCED_DOMAIN(PP, TC, nd, options, i, D, rVD)
1486 Param_Vertices *V;
1488 s[i].E = evalue_zero();
1489 s[i].D = rVD;
1491 FORALL_PVertex_in_ParamPolyhedron(V,D,PP) // _i is internal counter
1492 if (!et->vE[_i])
1493 try {
1494 et->decompose_at(V, _i, options);
1495 } catch (OrthogonalException &e) {
1496 FORALL_REDUCED_DOMAIN_RESET;
1497 for (; i >= 0; --i) {
1498 evalue_free(s[i].E);
1499 Domain_Free(s[i].D);
1501 goto try_again;
1503 eadd(et->vE[_i] , s[i].E);
1504 END_FORALL_PVertex_in_ParamPolyhedron;
1505 evalue_range_reduction_in_domain(s[i].E, rVD);
1506 END_FORALL_REDUCED_DOMAIN
1507 Polyhedron_Free(TC);
1509 delete et;
1510 eres = evalue_from_section_array(s, nd);
1511 delete [] s;
1513 return eres;
1516 static evalue* barvinok_enumerate_ev_f(Polyhedron *P, Polyhedron* C,
1517 barvinok_options *options)
1519 unsigned nparam = C->Dimension;
1520 bool do_scale = options->approximation_method == BV_APPROX_SCALE;
1522 if (options->summation == BV_SUM_EULER)
1523 return barvinok_summate_unweighted(P, C, euler_summate, options);
1525 if (options->approximation_method == BV_APPROX_VOLUME)
1526 return Param_Polyhedron_Volume(P, C, options);
1528 if (P->Dimension - nparam == 1 && !do_scale)
1529 return ParamLine_Length(P, C, options);
1531 Param_Polyhedron *PP = NULL;
1532 evalue *eres;
1534 if (do_scale) {
1535 eres = scale_bound(P, C, options);
1536 if (eres)
1537 return eres;
1540 PP = Polyhedron2Param_Polyhedron(P, C, options);
1542 if (do_scale)
1543 eres = scale(PP, P, C, options);
1544 else
1545 eres = Param_Polyhedron_Enumerate(PP, P, C, options);
1547 if (PP)
1548 Param_Polyhedron_Free(PP);
1550 return eres;
1553 Enumeration* barvinok_enumerate(Polyhedron *P, Polyhedron* C, unsigned MaxRays)
1555 evalue *EP = barvinok_enumerate_ev(P, C, MaxRays);
1557 return partition2enumeration(EP);
1560 evalue* barvinok_enumerate_union(Polyhedron *D, Polyhedron* C, unsigned MaxRays)
1562 evalue *EP;
1563 gen_fun *gf = barvinok_enumerate_union_series(D, C, MaxRays);
1564 EP = *gf;
1565 delete gf;
1566 return EP;
1569 evalue *barvinok_summate(evalue *e, int nvar, struct barvinok_options *options)
1571 if (options->summation == BV_SUM_EULER)
1572 return euler_summate(e, nvar, options);
1573 else if (options->summation == BV_SUM_LAURENT)
1574 return laurent_summate(e, nvar, options);
1575 else if (options->summation == BV_SUM_BERNOULLI)
1576 return Bernoulli_sum_evalue(e, nvar, options);
1577 else
1578 return evalue_sum(e, nvar, options->MaxRays);
1581 /* Turn unweighted counting problem into "weighted" counting problem
1582 * with weight equal to 1 and call "summate" on this weighted problem.
1584 static evalue *barvinok_summate_unweighted(Polyhedron *P, Polyhedron *C,
1585 evalue *(*summate)(evalue *, unsigned, struct barvinok_options *options),
1586 struct barvinok_options *options)
1588 Polyhedron *CA, *D;
1589 evalue e;
1590 evalue *sum;
1592 if (emptyQ(P) || emptyQ(C))
1593 return evalue_zero();
1595 CA = align_context(C, P->Dimension, options->MaxRays);
1596 D = DomainIntersection(P, CA, options->MaxRays);
1597 Domain_Free(CA);
1599 if (emptyQ(D)) {
1600 Domain_Free(D);
1601 return evalue_zero();
1604 value_init(e.d);
1605 e.x.p = new_enode(partition, 2, P->Dimension);
1606 EVALUE_SET_DOMAIN(e.x.p->arr[0], D);
1607 evalue_set_si(&e.x.p->arr[1], 1, 1);
1608 sum = summate(&e, P->Dimension - C->Dimension, options);
1609 free_evalue_refs(&e);
1610 return sum;