update isl for help message printing
[barvinok/uuh.git] / summate.c
blob393ffc06ef4c225b9a39b153c42027cec2679228
1 #include <isl_set_polylib.h>
2 #include <barvinok/options.h>
3 #include <barvinok/util.h>
4 #include "bernoulli.h"
5 #include "euler.h"
6 #include "laurent.h"
7 #include "laurent_old.h"
8 #include "summate.h"
9 #include "section_array.h"
10 #include "remove_equalities.h"
12 extern evalue *evalue_outer_floor(evalue *e);
13 extern int evalue_replace_floor(evalue *e, const evalue *floor, int var);
14 extern void evalue_drop_floor(evalue *e, const evalue *floor);
16 #define ALLOC(type) (type*)malloc(sizeof(type))
17 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
19 /* Apply the variable transformation specified by T and CP on
20 * the polynomial e. T expresses the old variables in terms
21 * of the new variables (and optionally also the new parameters),
22 * while CP expresses the old parameters in terms of the new
23 * parameters.
25 static void transform_polynomial(evalue *E, Matrix *T, Matrix *CP,
26 unsigned nvar, unsigned nparam,
27 unsigned new_nvar, unsigned new_nparam)
29 int j;
30 evalue **subs;
32 subs = ALLOCN(evalue *, nvar+nparam);
34 for (j = 0; j < nvar; ++j) {
35 if (T)
36 subs[j] = affine2evalue(T->p[j], T->p[T->NbRows-1][T->NbColumns-1],
37 T->NbColumns-1);
38 else
39 subs[j] = evalue_var(j);
41 for (j = 0; j < nparam; ++j) {
42 if (CP)
43 subs[nvar+j] = affine2evalue(CP->p[j], CP->p[nparam][new_nparam],
44 new_nparam);
45 else
46 subs[nvar+j] = evalue_var(j);
47 evalue_shift_variables(subs[nvar+j], 0, new_nvar);
50 evalue_substitute(E, subs);
51 reduce_evalue(E);
53 for (j = 0; j < nvar+nparam; ++j)
54 evalue_free(subs[j]);
55 free(subs);
58 static evalue *sum_over_polytope_with_equalities(Polyhedron *P, evalue *E,
59 unsigned nvar,
60 struct evalue_section_array *sections,
61 struct barvinok_options *options)
63 unsigned dim = P->Dimension;
64 unsigned new_dim, new_nparam;
65 Matrix *T = NULL, *CP = NULL;
66 evalue *sum;
68 if (emptyQ(P))
69 return evalue_zero();
71 assert(P->NbEq > 0);
73 remove_all_equalities(&P, NULL, &CP, &T, dim-nvar, options->MaxRays);
75 if (emptyQ(P)) {
76 Polyhedron_Free(P);
77 return evalue_zero();
80 new_nparam = CP ? CP->NbColumns-1 : dim - nvar;
81 new_dim = T ? T->NbColumns-1 : nvar + new_nparam;
83 /* We can avoid these substitutions if E is a constant */
84 E = evalue_dup(E);
85 transform_polynomial(E, T, CP, nvar, dim-nvar,
86 new_dim-new_nparam, new_nparam);
88 if (new_dim-new_nparam > 0) {
89 sum = barvinok_sum_over_polytope(P, E, new_dim-new_nparam,
90 sections, options);
91 evalue_free(E);
92 Polyhedron_Free(P);
93 } else {
94 sum = ALLOC(evalue);
95 value_init(sum->d);
96 sum->x.p = new_enode(partition, 2, new_dim);
97 EVALUE_SET_DOMAIN(sum->x.p->arr[0], P);
98 value_clear(sum->x.p->arr[1].d);
99 sum->x.p->arr[1] = *E;
100 free(E);
103 if (CP) {
104 evalue_backsubstitute(sum, CP, options->MaxRays);
105 Matrix_Free(CP);
108 if (T)
109 Matrix_Free(T);
111 return sum;
114 static evalue *sum_base(Polyhedron *P, evalue *E, unsigned nvar,
115 struct barvinok_options *options)
117 if (options->summation == BV_SUM_EULER)
118 return euler_summate(P, E, nvar, options);
119 else if (options->summation == BV_SUM_LAURENT)
120 return laurent_summate(P, E, nvar, options);
121 else if (options->summation == BV_SUM_LAURENT_OLD)
122 return laurent_summate_old(P, E, nvar, options);
123 assert(0);
126 /* Count the number of non-zero terms in e when viewed as a polynomial
127 * in only the first nvar variables. "count" is the number counted
128 * so far.
130 static int evalue_count_terms(const evalue *e, unsigned nvar, int count)
132 int i;
134 if (EVALUE_IS_ZERO(*e))
135 return count;
137 if (value_zero_p(e->d))
138 assert(e->x.p->type == polynomial);
139 if (value_notzero_p(e->d) || e->x.p->pos >= nvar+1)
140 return count+1;
142 for (i = 0; i < e->x.p->size; ++i)
143 count = evalue_count_terms(&e->x.p->arr[i], nvar, count);
145 return count;
148 /* Create placeholder structure for unzipping.
149 * A "polynomial" is created with size terms in variable pos,
150 * with each term having itself as coefficient.
152 static evalue *create_placeholder(int size, int pos)
154 int i, j;
155 evalue *E = ALLOC(evalue);
156 value_init(E->d);
157 E->x.p = new_enode(polynomial, size, pos+1);
158 for (i = 0; i < size; ++i) {
159 E->x.p->arr[i].x.p = new_enode(polynomial, i+1, pos+1);
160 for (j = 0; j < i; ++j)
161 evalue_set_si(&E->x.p->arr[i].x.p->arr[j], 0, 1);
162 evalue_set_si(&E->x.p->arr[i].x.p->arr[i], 1, 1);
164 return E;
167 /* Interchange each non-zero term in e (when viewed as a polynomial
168 * in only the first nvar variables) with a placeholder in ph (created
169 * by create_placeholder), resulting in two polynomials in the
170 * placeholder variable such that for each non-zero term in e
171 * there is a power of the placeholder variable such that the factors
172 * in the first nvar variables form the coefficient of that power in
173 * the first polynomial (e) and the factors in the remaining variables
174 * form the coefficient of that power in the second polynomial (ph).
176 static int evalue_unzip_terms(evalue *e, evalue *ph, unsigned nvar, int count)
178 int i;
180 if (EVALUE_IS_ZERO(*e))
181 return count;
183 if (value_zero_p(e->d))
184 assert(e->x.p->type == polynomial);
185 if (value_notzero_p(e->d) || e->x.p->pos >= nvar+1) {
186 evalue t = *e;
187 *e = ph->x.p->arr[count];
188 ph->x.p->arr[count] = t;
189 return count+1;
192 for (i = 0; i < e->x.p->size; ++i)
193 count = evalue_unzip_terms(&e->x.p->arr[i], ph, nvar, count);
195 return count;
198 /* Remove n variables at pos (0-based) from the polyhedron P.
199 * Each of these variables is assumed to be completely free,
200 * i.e., there is a line in the polyhedron corresponding to
201 * each of these variables.
203 static Polyhedron *Polyhedron_Remove_Columns(Polyhedron *P, unsigned pos,
204 unsigned n)
206 int i, j;
207 unsigned NbConstraints = 0;
208 unsigned NbRays = 0;
209 Polyhedron *Q;
211 if (n == 0)
212 return P;
214 assert(pos <= P->Dimension);
216 if (POL_HAS(P, POL_INEQUALITIES))
217 NbConstraints = P->NbConstraints;
218 if (POL_HAS(P, POL_POINTS))
219 NbRays = P->NbRays - n;
221 Q = Polyhedron_Alloc(P->Dimension - n, NbConstraints, NbRays);
222 if (POL_HAS(P, POL_INEQUALITIES)) {
223 Q->NbEq = P->NbEq;
224 for (i = 0; i < P->NbConstraints; ++i) {
225 Vector_Copy(P->Constraint[i], Q->Constraint[i], 1+pos);
226 Vector_Copy(P->Constraint[i]+1+pos+n, Q->Constraint[i]+1+pos,
227 Q->Dimension-pos+1);
230 if (POL_HAS(P, POL_POINTS)) {
231 Q->NbBid = P->NbBid - n;
232 for (i = 0; i < n; ++i)
233 value_set_si(Q->Ray[i][1+pos+i], 1);
234 for (i = 0, j = 0; i < P->NbRays; ++i) {
235 int line = First_Non_Zero(P->Ray[i], 1+P->Dimension+1);
236 assert(line != -1);
237 if (line-1 >= pos && line-1 < pos+n) {
238 ++j;
239 assert(j <= n);
240 continue;
242 assert(i-j < Q->NbRays);
243 Vector_Copy(P->Ray[i], Q->Ray[i-j], 1+pos);
244 Vector_Copy(P->Ray[i]+1+pos+n, Q->Ray[i-j]+1+pos,
245 Q->Dimension-pos+1);
248 POL_SET(Q, POL_VALID);
249 if (POL_HAS(P, POL_INEQUALITIES))
250 POL_SET(Q, POL_INEQUALITIES);
251 if (POL_HAS(P, POL_POINTS))
252 POL_SET(Q, POL_POINTS);
253 if (POL_HAS(P, POL_VERTICES))
254 POL_SET(Q, POL_VERTICES);
255 return Q;
258 /* Remove n variables at pos (0-based) from the union of polyhedra P.
259 * Each of these variables is assumed to be completely free,
260 * i.e., there is a line in the polyhedron corresponding to
261 * each of these variables.
263 static Polyhedron *Domain_Remove_Columns(Polyhedron *P, unsigned pos,
264 unsigned n)
266 Polyhedron *R;
267 Polyhedron **next = &R;
269 for (; P; P = P->next) {
270 *next = Polyhedron_Remove_Columns(P, pos, n);
271 next = &(*next)->next;
273 return R;
276 /* Drop n parameters starting at first from partition evalue e */
277 static void drop_parameters(evalue *e, int first, int n)
279 int i;
281 if (EVALUE_IS_ZERO(*e))
282 return;
284 assert(value_zero_p(e->d) && e->x.p->type == partition);
285 for (i = 0; i < e->x.p->size/2; ++i) {
286 Polyhedron *P = EVALUE_DOMAIN(e->x.p->arr[2*i]);
287 Polyhedron *Q = Domain_Remove_Columns(P, first, n);
288 EVALUE_SET_DOMAIN(e->x.p->arr[2*i], Q);
289 Domain_Free(P);
290 evalue_shift_variables(&e->x.p->arr[2*i+1], first, -n);
292 e->x.p->pos -= n;
295 static void extract_term_into(const evalue *src, int var, int exp, evalue *dst)
297 int i;
299 if (value_notzero_p(src->d) ||
300 src->x.p->type != polynomial ||
301 src->x.p->pos > var+1) {
302 if (exp == 0)
303 evalue_copy(dst, src);
304 else
305 evalue_set_si(dst, 0, 1);
306 return;
309 if (src->x.p->pos == var+1) {
310 if (src->x.p->size > exp)
311 evalue_copy(dst, &src->x.p->arr[exp]);
312 else
313 evalue_set_si(dst, 0, 1);
314 return;
317 dst->x.p = new_enode(polynomial, src->x.p->size, src->x.p->pos);
318 for (i = 0; i < src->x.p->size; ++i)
319 extract_term_into(&src->x.p->arr[i], var, exp,
320 &dst->x.p->arr[i]);
323 /* Extract the coefficient of var^exp.
325 static evalue *extract_term(const evalue *e, int var, int exp)
327 int i;
328 evalue *res;
330 if (EVALUE_IS_ZERO(*e))
331 return evalue_zero();
333 assert(value_zero_p(e->d) && e->x.p->type == partition);
334 res = ALLOC(evalue);
335 value_init(res->d);
336 res->x.p = new_enode(partition, e->x.p->size, e->x.p->pos);
337 for (i = 0; i < e->x.p->size/2; ++i) {
338 EVALUE_SET_DOMAIN(res->x.p->arr[2*i],
339 Domain_Copy(EVALUE_DOMAIN(e->x.p->arr[2*i])));
340 extract_term_into(&e->x.p->arr[2*i+1], var, exp,
341 &res->x.p->arr[2*i+1]);
342 reduce_evalue(&res->x.p->arr[2*i+1]);
344 return res;
347 /* Insert n free variables at pos (0-based) in the polyhedron P.
349 static Polyhedron *Polyhedron_Insert_Columns(Polyhedron *P, unsigned pos,
350 unsigned n)
352 int i;
353 unsigned NbConstraints = 0;
354 unsigned NbRays = 0;
355 Polyhedron *Q;
357 if (!P)
358 return P;
359 if (n == 0)
360 return P;
362 assert(pos <= P->Dimension);
364 if (POL_HAS(P, POL_INEQUALITIES))
365 NbConstraints = P->NbConstraints;
366 if (POL_HAS(P, POL_POINTS))
367 NbRays = P->NbRays + n;
369 Q = Polyhedron_Alloc(P->Dimension+n, NbConstraints, NbRays);
370 if (POL_HAS(P, POL_INEQUALITIES)) {
371 Q->NbEq = P->NbEq;
372 for (i = 0; i < P->NbConstraints; ++i) {
373 Vector_Copy(P->Constraint[i], Q->Constraint[i], 1+pos);
374 Vector_Copy(P->Constraint[i]+1+pos, Q->Constraint[i]+1+pos+n,
375 P->Dimension-pos+1);
378 if (POL_HAS(P, POL_POINTS)) {
379 Q->NbBid = P->NbBid + n;
380 for (i = 0; i < n; ++i)
381 value_set_si(Q->Ray[i][1+pos+i], 1);
382 for (i = 0; i < P->NbRays; ++i) {
383 Vector_Copy(P->Ray[i], Q->Ray[n+i], 1+pos);
384 Vector_Copy(P->Ray[i]+1+pos, Q->Ray[n+i]+1+pos+n,
385 P->Dimension-pos+1);
388 POL_SET(Q, POL_VALID);
389 if (POL_HAS(P, POL_INEQUALITIES))
390 POL_SET(Q, POL_INEQUALITIES);
391 if (POL_HAS(P, POL_POINTS))
392 POL_SET(Q, POL_POINTS);
393 if (POL_HAS(P, POL_VERTICES))
394 POL_SET(Q, POL_VERTICES);
395 return Q;
398 /* Perform summation of e over a list of 1 or more factors F, with context C.
399 * nvar is the total number of variables in the remaining factors.
400 * extra is the number of placeholder parameters introduced in e,
401 * but not (yet) in F or C.
403 * If there is only one factor left, F is intersected with the
404 * context C, the placeholder variables are added, and then
405 * e is summed over the resulting parametric polytope.
407 * If there is more than one factor left, we create two polynomials
408 * in a new placeholder variable (which is placed after the regular
409 * parameters, but before any previously introduced placeholder
410 * variables) that has the factors of the variables in the first
411 * factor of F and the factor of the remaining variables of
412 * each term as its coefficients.
413 * These two polynomials are then summed over their domains
414 * and afterwards the results are combined and the placeholder
415 * variable is removed again.
417 static evalue *sum_factors(Polyhedron *F, Polyhedron *C, evalue *e,
418 unsigned nvar, unsigned extra,
419 struct barvinok_options *options)
421 Polyhedron *P = F;
422 unsigned nparam = C->Dimension;
423 unsigned F_var = F->Dimension - C->Dimension;
424 int i, n;
425 evalue *s1, *s2, *s;
426 evalue *ph;
428 if (!F->next) {
429 Polyhedron *CA = align_context(C, nvar+nparam, options->MaxRays);
430 Polyhedron *P = DomainIntersection(F, CA, options->MaxRays);
431 Polyhedron *Q = Polyhedron_Insert_Columns(P, nvar+nparam, extra);
432 Polyhedron_Free(CA);
433 Polyhedron_Free(F);
434 Polyhedron_Free(P);
435 evalue *sum = sum_base(Q, e, nvar, options);
436 Polyhedron_Free(Q);
437 return sum;
440 n = evalue_count_terms(e, F_var, 0);
441 ph = create_placeholder(n, nvar+nparam);
442 evalue_shift_variables(e, nvar+nparam, 1);
443 evalue_unzip_terms(e, ph, F_var, 0);
444 evalue_shift_variables(e, nvar, -(nvar-F_var));
445 evalue_reorder_terms(ph);
446 evalue_shift_variables(ph, 0, -F_var);
448 s2 = sum_factors(F->next, C, ph, nvar-F_var, extra+1, options);
449 evalue_free(ph);
450 F->next = NULL;
451 s1 = sum_factors(F, C, e, F_var, extra+1, options);
453 if (n == 1) {
454 /* remove placeholder "polynomial" */
455 reduce_evalue(s1);
456 emul(s1, s2);
457 evalue_free(s1);
458 drop_parameters(s2, nparam, 1);
459 return s2;
462 s = evalue_zero();
463 for (i = 0; i < n; ++i) {
464 evalue *t1, *t2;
465 t1 = extract_term(s1, nparam, i);
466 t2 = extract_term(s2, nparam, i);
467 emul(t1, t2);
468 eadd(t2, s);
469 evalue_free(t1);
470 evalue_free(t2);
472 evalue_free(s1);
473 evalue_free(s2);
475 drop_parameters(s, nparam, 1);
476 return s;
479 /* Perform summation over a product of factors F, obtained using
480 * variable transformation T from the original problem specification.
482 * We first perform the corresponding transformation on the polynomial E,
483 * compute the common context over all factors and then perform
484 * the actual summation over the factors.
486 static evalue *sum_product(Polyhedron *F, evalue *E, Matrix *T, unsigned nparam,
487 struct barvinok_options *options)
489 int i;
490 Matrix *T2;
491 unsigned nvar = T->NbRows;
492 Polyhedron *C;
493 evalue *sum;
495 assert(nvar == T->NbColumns);
496 T2 = Matrix_Alloc(nvar+1, nvar+1);
497 for (i = 0; i < nvar; ++i)
498 Vector_Copy(T->p[i], T2->p[i], nvar);
499 value_set_si(T2->p[nvar][nvar], 1);
501 transform_polynomial(E, T2, NULL, nvar, nparam, nvar, nparam);
503 C = Factor_Context(F, nparam, options->MaxRays);
504 if (F->Dimension == nparam) {
505 Polyhedron *T = F;
506 F = F->next;
507 T->next = NULL;
508 Polyhedron_Free(T);
510 sum = sum_factors(F, C, E, nvar, 0, options);
512 Polyhedron_Free(C);
513 Matrix_Free(T2);
514 Matrix_Free(T);
515 return sum;
518 /* Add two constraints corresponding to floor = floor(e/d),
520 * e - d t >= 0
521 * -e + d t + d-1 >= 0
523 * e is assumed to be an affine expression.
525 Polyhedron *add_floor_var(Polyhedron *P, unsigned nvar, const evalue *floor,
526 struct barvinok_options *options)
528 int i;
529 unsigned dim = P->Dimension+1;
530 Matrix *M = Matrix_Alloc(P->NbConstraints+2, 2+dim);
531 Polyhedron *CP;
532 Value *d = &M->p[0][1+nvar];
533 evalue_extract_affine(floor, M->p[0]+1, M->p[0]+1+dim, d);
534 value_oppose(*d, *d);
535 value_set_si(M->p[0][0], 1);
536 value_set_si(M->p[1][0], 1);
537 Vector_Oppose(M->p[0]+1, M->p[1]+1, M->NbColumns-1);
538 value_subtract(M->p[1][1+dim], M->p[1][1+dim], *d);
539 value_decrement(M->p[1][1+dim], M->p[1][1+dim]);
541 for (i = 0; i < P->NbConstraints; ++i) {
542 Vector_Copy(P->Constraint[i], M->p[i+2], 1+nvar);
543 Vector_Copy(P->Constraint[i]+1+nvar, M->p[i+2]+1+nvar+1, dim-nvar-1+1);
546 CP = Constraints2Polyhedron(M, options->MaxRays);
547 Matrix_Free(M);
548 return CP;
551 static evalue *evalue_add(evalue *a, evalue *b)
553 if (!a)
554 return b;
555 if (!b)
556 return a;
557 eadd(a, b);
558 evalue_free(a);
559 return b;
562 /* Compute sum of a step-polynomial over a polytope by grouping
563 * terms containing the same floor-expressions and introducing
564 * new variables for each such expression.
565 * In particular, while there is any floor-expression left,
566 * the step-polynomial is split into a polynomial containing
567 * the expression, which is then converted to a new variable,
568 * and a polynomial not containing the expression.
570 static evalue *sum_step_polynomial(Polyhedron *P, evalue *E, unsigned nvar,
571 struct barvinok_options *options)
573 evalue *floor;
574 evalue *cur = E;
575 evalue *sum = NULL;
576 evalue *t;
578 while ((floor = evalue_outer_floor(cur))) {
579 Polyhedron *CP;
580 evalue *converted;
581 evalue *converted_floor;
583 /* Ignore floors that do not depend on variables. */
584 if (value_notzero_p(floor->d) || floor->x.p->pos >= nvar+1)
585 break;
587 converted = evalue_dup(cur);
588 converted_floor = evalue_dup(floor);
589 evalue_shift_variables(converted, nvar, 1);
590 evalue_shift_variables(converted_floor, nvar, 1);
591 evalue_replace_floor(converted, converted_floor, nvar);
592 CP = add_floor_var(P, nvar, converted_floor, options);
593 evalue_free(converted_floor);
594 t = sum_step_polynomial(CP, converted, nvar+1, options);
595 evalue_free(converted);
596 Polyhedron_Free(CP);
597 sum = evalue_add(t, sum);
599 if (cur == E)
600 cur = evalue_dup(cur);
601 evalue_drop_floor(cur, floor);
602 evalue_free(floor);
604 if (floor) {
605 evalue_floor2frac(cur);
606 evalue_free(floor);
609 if (EVALUE_IS_ZERO(*cur))
610 t = NULL;
611 else {
612 Matrix *T;
613 unsigned nparam = P->Dimension - nvar;
614 Polyhedron *F = Polyhedron_Factor(P, nparam, &T, options->MaxRays);
615 if (!F)
616 t = sum_base(P, cur, nvar, options);
617 else {
618 if (cur == E)
619 cur = evalue_dup(cur);
620 t = sum_product(F, cur, T, nparam, options);
624 if (E != cur)
625 evalue_free(cur);
627 return evalue_add(t, sum);
630 evalue *barvinok_sum_over_polytope(Polyhedron *P, evalue *E, unsigned nvar,
631 struct evalue_section_array *sections,
632 struct barvinok_options *options)
634 if (P->NbEq)
635 return sum_over_polytope_with_equalities(P, E, nvar, sections, options);
637 if (options->summation == BV_SUM_BERNOULLI)
638 return bernoulli_summate(P, E, nvar, sections, options);
639 else if (options->summation == BV_SUM_BOX)
640 return box_summate(P, E, nvar, options->MaxRays);
642 evalue_frac2floor2(E, 0);
644 return sum_step_polynomial(P, E, nvar, options);
647 evalue *barvinok_summate(evalue *e, int nvar, struct barvinok_options *options)
649 int i;
650 struct evalue_section_array sections;
651 evalue *sum;
653 assert(nvar >= 0);
654 if (nvar == 0 || EVALUE_IS_ZERO(*e))
655 return evalue_dup(e);
657 assert(value_zero_p(e->d));
658 assert(e->x.p->type == partition);
660 evalue_section_array_init(&sections);
661 sum = evalue_zero();
663 for (i = 0; i < e->x.p->size/2; ++i) {
664 Polyhedron *D;
665 for (D = EVALUE_DOMAIN(e->x.p->arr[2*i]); D; D = D->next) {
666 Polyhedron *next = D->next;
667 evalue *tmp;
668 D->next = NULL;
670 tmp = barvinok_sum_over_polytope(D, &e->x.p->arr[2*i+1], nvar,
671 &sections, options);
672 assert(tmp);
673 eadd(tmp, sum);
674 evalue_free(tmp);
676 D->next = next;
680 free(sections.s);
682 reduce_evalue(sum);
683 return sum;
686 static int add_guarded_qp(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
687 void *user)
689 Polyhedron *D, *P;
690 isl_pw_qpolynomial **sum = (isl_pw_qpolynomial **) user;
691 struct barvinok_options *options;
692 struct evalue_section_array sections;
693 isl_dim *dim = NULL;
694 int nvar;
695 evalue *e;
697 options = barvinok_options_new_with_defaults();
699 if (!set || !qp)
700 goto error;
702 e = isl_qpolynomial_to_evalue(qp);
703 if (!e)
704 goto error;
706 dim = isl_set_get_dim(set);
707 nvar = isl_dim_size(dim, isl_dim_set);
708 dim = isl_dim_drop(dim, isl_dim_set, 0, nvar);
710 evalue_section_array_init(&sections);
712 set = isl_set_make_disjoint(set);
713 D = isl_set_to_polylib(set);
715 for (P = D; P; P = P->next) {
716 Polyhedron *next = P->next;
717 evalue *tmp;
718 isl_pw_qpolynomial *pwqp;
720 P->next = NULL;
722 tmp = barvinok_sum_over_polytope(P, e, nvar, &sections, options);
723 assert(tmp);
724 pwqp = isl_pw_qpolynomial_from_evalue(isl_dim_copy(dim), tmp);
725 evalue_free(tmp);
726 *sum = isl_pw_qpolynomial_add(*sum, pwqp);
728 P->next = next;
731 Domain_Free(D);
733 free(sections.s);
735 isl_dim_free(dim);
737 evalue_free(e);
739 isl_set_free(set);
740 isl_qpolynomial_free(qp);
742 barvinok_options_free(options);
744 return 0;
745 error:
746 isl_set_free(set);
747 isl_qpolynomial_free(qp);
748 barvinok_options_free(options);
749 return -1;
752 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sum(
753 __isl_take isl_pw_qpolynomial *pwqp)
755 int nvar;
756 isl_dim *dim = NULL;
757 isl_pw_qpolynomial *sum;
759 if (!pwqp)
760 return NULL;
762 nvar = isl_pw_qpolynomial_dim(pwqp, isl_dim_set);
763 if (nvar == 0)
764 return pwqp;
766 dim = isl_pw_qpolynomial_get_dim(pwqp);
767 dim = isl_dim_drop(dim, isl_dim_set, 0, nvar);
769 sum = isl_pw_qpolynomial_zero(dim);
771 if (isl_pw_qpolynomial_foreach_lifted_piece(pwqp, add_guarded_qp, &sum) < 0)
772 goto error;
774 isl_pw_qpolynomial_free(pwqp);
776 return sum;
777 error:
778 isl_pw_qpolynomial_free(pwqp);
779 isl_pw_qpolynomial_free(sum);
780 return NULL;
783 evalue *evalue_sum(evalue *E, int nvar, unsigned MaxRays)
785 evalue *sum;
786 struct barvinok_options *options = barvinok_options_new_with_defaults();
787 options->MaxRays = MaxRays;
788 sum = barvinok_summate(E, nvar, options);
789 barvinok_options_free(options);
790 return sum;
793 evalue *esum(evalue *e, int nvar)
795 evalue *sum;
796 struct barvinok_options *options = barvinok_options_new_with_defaults();
797 sum = barvinok_summate(e, nvar, options);
798 barvinok_options_free(options);
799 return sum;
802 /* Turn unweighted counting problem into "weighted" counting problem
803 * with weight equal to 1 and call barvinok_summate on this weighted problem.
805 evalue *barvinok_summate_unweighted(Polyhedron *P, Polyhedron *C,
806 struct barvinok_options *options)
808 Polyhedron *CA, *D;
809 evalue e;
810 evalue *sum;
812 if (emptyQ(P) || emptyQ(C))
813 return evalue_zero();
815 CA = align_context(C, P->Dimension, options->MaxRays);
816 D = DomainIntersection(P, CA, options->MaxRays);
817 Domain_Free(CA);
819 if (emptyQ(D)) {
820 Domain_Free(D);
821 return evalue_zero();
824 value_init(e.d);
825 e.x.p = new_enode(partition, 2, P->Dimension);
826 EVALUE_SET_DOMAIN(e.x.p->arr[0], D);
827 evalue_set_si(&e.x.p->arr[1], 1, 1);
828 sum = barvinok_summate(&e, P->Dimension - C->Dimension, options);
829 free_evalue_refs(&e);
830 return sum;