2 #include <barvinok/barvinok.h>
3 #include <barvinok/util.h>
4 #include <barvinok/options.h>
6 #include "reduce_domain.h"
7 #include "param_util.h"
9 #define ALLOC(type) (type*)malloc(sizeof(type))
10 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
12 /* If a vertex is described by A x + B p + c = 0, then
13 * M = [A B] and we want to compute a linear transformation L such
14 * that H L = A and H \Z contains both A \Z and B \Z.
16 * [ A B ] = [ H 0 ] [ U_11 U_12 ]
19 * U_11 is the required linear transformation.
20 * Note that this also works if M has more rows than there are variables,
21 * i.e., if some rows in M are linear combinations of other rows.
22 * These extra rows only affect and H and not U.
24 static Lattice
*extract_lattice(Matrix
*M
, unsigned nvar
)
27 Matrix
*H
, *Q
, *U
, *Li
;
31 left_hermite(M
, &H
, &Q
, &U
);
34 Li
= Matrix_Alloc(nvar
+1, nvar
+1);
35 L
= Matrix_Alloc(nvar
+1, nvar
+1);
36 value_set_si(Li
->p
[nvar
][nvar
], 1);
38 for (row
= 0; row
< nvar
; ++row
)
39 Vector_Copy(Q
->p
[row
], Li
->p
[row
], nvar
);
43 ok
= Matrix_Inverse(Li
, L
);
50 /* Returns the smallest (wrt inclusion) lattice that contains both X and Y */
51 static Lattice
*LatticeJoin(Lattice
*X
, Lattice
*Y
)
54 int dim
= X
->NbRows
-1;
58 Matrix
*M
, *H
, *U
, *Q
;
60 assert(X
->NbColumns
-1 == dim
);
61 assert(Y
->NbRows
-1 == dim
);
62 assert(Y
->NbColumns
-1 == dim
);
67 M
= Matrix_Alloc(dim
, 2*dim
);
68 value_lcm(lcm
, X
->p
[dim
][dim
], Y
->p
[dim
][dim
]);
70 value_division(tmp
, lcm
, X
->p
[dim
][dim
]);
71 for (i
= 0; i
< dim
; ++i
)
72 Vector_Scale(X
->p
[i
], M
->p
[i
], tmp
, dim
);
73 value_division(tmp
, lcm
, Y
->p
[dim
][dim
]);
74 for (i
= 0; i
< dim
; ++i
)
75 Vector_Scale(Y
->p
[i
], M
->p
[i
]+dim
, tmp
, dim
);
77 left_hermite(M
, &H
, &Q
, &U
);
82 L
= Matrix_Alloc(dim
+1, dim
+1);
83 value_assign(L
->p
[dim
][dim
], lcm
);
84 for (i
= 0; i
< dim
; ++i
)
85 Vector_Copy(H
->p
[i
], L
->p
[i
], dim
);
93 static void Param_Vertex_Image(Param_Vertices
*V
, Matrix
*T
)
95 unsigned nvar
= V
->Vertex
->NbRows
;
96 unsigned nparam
= V
->Vertex
->NbColumns
- 2;
100 Param_Vertex_Common_Denominator(V
);
101 Vertex
= Matrix_Alloc(V
->Vertex
->NbRows
, V
->Vertex
->NbColumns
);
102 Matrix_Product(T
, V
->Vertex
, Vertex
);
103 for (i
= 0; i
< nvar
; ++i
) {
104 value_assign(Vertex
->p
[i
][nparam
+1], V
->Vertex
->p
[i
][nparam
+1]);
105 Vector_Normalize(Vertex
->p
[i
], nparam
+2);
107 Matrix_Free(V
->Vertex
);
111 static void apply_expansion(Param_Polyhedron
*PP
,
112 Matrix
*expansion
, unsigned MaxRays
)
115 unsigned nparam
= PP
->V
->Vertex
->NbColumns
- 2;
116 unsigned nvar
= PP
->V
->Vertex
->NbRows
;
119 constraint
= Vector_Alloc(nvar
+nparam
+1);
120 for (i
= 0; i
< PP
->Constraints
->NbRows
; ++i
) {
121 Vector_Matrix_Product(PP
->Constraints
->p
[i
]+1, expansion
, constraint
->p
);
122 Vector_Copy(constraint
->p
, PP
->Constraints
->p
[i
]+1, nvar
+nparam
+1);
123 Vector_Normalize(PP
->Constraints
->p
[i
]+1, nvar
+nparam
+1);
125 Vector_Free(constraint
);
128 /* Scales the parametric polyhedron with constraints vertices PP
129 * such that the number of integer points can be represented by a polynomial.
130 * The vertices of "PP" are adapted according to the scaling.
131 * The scaling factor is returned in *det.
132 * The transformation that maps the new coordinates to the original
133 * coordinates is returned in *Lat (if Lat != NULL).
134 * The enumerator of the scaled parametric polyhedron should be divided
135 * by this number to obtain an approximation of the enumerator of the
136 * original parametric polyhedron.
138 * The algorithm is described in "Approximating Ehrhart Polynomials using
139 * affine transformations" by B. Meister.
141 static void Param_Polyhedron_Scale_Integer_Slow(Param_Polyhedron
*PP
,
143 Value
*det
, unsigned MaxRays
)
148 Lattice
*L
= NULL
, *Li
;
157 nparam
= PP
->V
->Vertex
->NbColumns
- 2;
158 nvar
= PP
->V
->Vertex
->NbRows
;
160 for (V
= PP
->V
; V
; V
= V
->next
) {
164 unsigned *supporting
;
168 supporting
= supporting_constraints(PP
->Constraints
, V
, &n
);
169 M
= Matrix_Alloc(n
, PP
->Constraints
->NbColumns
-2);
170 for (i
= 0, j
= 0, ix
= 0, bx
= MSB
; i
< PP
->Constraints
->NbRows
; ++i
) {
171 if (supporting
[ix
] & bx
)
172 Vector_Copy(PP
->Constraints
->p
[i
]+1, M
->p
[j
++],
173 PP
->Constraints
->NbColumns
-2);
177 L2
= extract_lattice(M
, nvar
);
183 Lattice
*L3
= LatticeJoin(L
, L2
);
191 *Lat
= Matrix_Copy(L
);
193 /* apply the variable expansion to the polyhedron (constraints) */
194 expansion
= Matrix_Alloc(nvar
+ nparam
+ 1, nvar
+ nparam
+ 1);
195 for (i
= 0; i
< nvar
; ++i
)
196 Vector_Copy(L
->p
[i
], expansion
->p
[i
], nvar
);
197 for (i
= nvar
; i
< nvar
+nparam
+1; ++i
)
198 value_assign(expansion
->p
[i
][i
], L
->p
[nvar
][nvar
]);
200 apply_expansion(PP
, expansion
, MaxRays
);
201 Matrix_Free(expansion
);
203 /* apply the variable expansion to the parametric vertices */
204 Li
= Matrix_Alloc(nvar
+1, nvar
+1);
205 ok
= Matrix_Inverse(L
, Li
);
208 assert(value_one_p(Li
->p
[nvar
][nvar
]));
209 T
= Matrix_Alloc(nvar
, nvar
);
210 value_set_si(*det
, 1);
211 for (i
= 0; i
< nvar
; ++i
) {
212 value_multiply(*det
, *det
, Li
->p
[i
][i
]);
213 Vector_Copy(Li
->p
[i
], T
->p
[i
], nvar
);
216 for (V
= PP
->V
; V
; V
= V
->next
)
217 Param_Vertex_Image(V
, T
);
221 /* Scales the parametric polyhedron with constraints vertices PP
222 * such that the number of integer points can be represented by a polynomial.
223 * The vertices of "PP" are adapted according to the scaling.
224 * The scaling factor is returned in *det.
225 * The transformation that maps the new coordinates to the original
226 * coordinates is returned in *Lat (if Lat != NULL).
227 * The enumerator of the scaled parametric polyhedron should be divided
228 * by this number to obtain an approximation of the enumerator of the
229 * original parametric polyhedron.
231 * The algorithm is described in "Approximating Ehrhart Polynomials using
232 * affine transformations" by B. Meister.
234 static void Param_Polyhedron_Scale_Integer_Fast(Param_Polyhedron
*PP
,
236 Value
*det
, unsigned MaxRays
)
239 int nb_param
, nb_vars
;
242 Value global_var_lcm
;
246 value_set_si(*det
, 1);
250 nb_param
= PP
->D
->Domain
->Dimension
;
251 nb_vars
= PP
->V
->Vertex
->NbRows
;
253 /* Scan the vertices and make an orthogonal expansion of the variable
255 /* a- prepare the array of common denominators */
256 denoms
= Vector_Alloc(nb_vars
);
257 value_init(global_var_lcm
);
260 /* b- scan the vertices and compute the variables' global lcms */
261 for (V
= PP
->V
; V
; V
= V
->next
) {
262 for (i
= 0; i
< nb_vars
; i
++) {
263 Vector_Gcd(V
->Vertex
->p
[i
], nb_param
, &tmp
);
264 value_gcd(tmp
, tmp
, V
->Vertex
->p
[i
][nb_param
+1]);
265 value_division(tmp
, V
->Vertex
->p
[i
][nb_param
+1], tmp
);
266 Lcm3(denoms
->p
[i
], tmp
, &denoms
->p
[i
]);
271 value_set_si(global_var_lcm
, 1);
272 for (i
= 0; i
< nb_vars
; i
++) {
273 value_multiply(*det
, *det
, denoms
->p
[i
]);
274 Lcm3(global_var_lcm
, denoms
->p
[i
], &global_var_lcm
);
278 for (V
= PP
->V
; V
; V
= V
->next
)
279 for (i
= 0; i
< nb_vars
; i
++) {
280 Vector_Scale(V
->Vertex
->p
[i
], V
->Vertex
->p
[i
], denoms
->p
[i
], nb_param
+1);
281 Vector_Normalize(V
->Vertex
->p
[i
], nb_param
+2);
284 /* the expansion can be actually writen as global_var_lcm.L^{-1} */
285 /* this is equivalent to multiply the rows of P by denoms_det */
286 for (i
= 0; i
< nb_vars
; i
++)
287 value_division(denoms
->p
[i
], global_var_lcm
, denoms
->p
[i
]);
289 /* OPT : we could use a vector instead of a diagonal matrix here (c- and d-).*/
290 /* c- make the quick expansion matrix */
291 expansion
= Matrix_Alloc(nb_vars
+nb_param
+1, nb_vars
+nb_param
+1);
292 for (i
= 0; i
< nb_vars
; i
++)
293 value_assign(expansion
->p
[i
][i
], denoms
->p
[i
]);
294 for (i
= nb_vars
; i
< nb_vars
+nb_param
+1; i
++)
295 value_assign(expansion
->p
[i
][i
], global_var_lcm
);
297 /* d- apply the variable expansion to the polyhedron */
298 apply_expansion(PP
, expansion
, MaxRays
);
301 Lattice
*L
= Matrix_Alloc(nb_vars
+1, nb_vars
+1);
302 for (i
= 0; i
< nb_vars
; ++i
)
303 value_assign(L
->p
[i
][i
], denoms
->p
[i
]);
304 value_assign(L
->p
[nb_vars
][nb_vars
], global_var_lcm
);
308 Matrix_Free(expansion
);
309 value_clear(global_var_lcm
);
313 /* Compute negated sum of all positive or negative coefficients in a row */
314 static void negated_sum(Value
*v
, int len
, int negative
, Value
*sum
)
318 value_set_si(*sum
, 0);
319 for (j
= 0; j
< len
; ++j
)
320 if (negative
? value_neg_p(v
[j
]) : value_pos_p(v
[j
]))
321 value_subtract(*sum
, *sum
, v
[j
]);
324 /* adapted from mpolyhedron_inflate in PolyLib */
325 Polyhedron
*Polyhedron_Flate(Polyhedron
*P
, unsigned nparam
, int inflate
,
329 int nvar
= P
->Dimension
- nparam
;
330 Matrix
*C
= Polyhedron2Constraints(P
);
335 /* subtract the sum of the negative coefficients of each inequality */
336 for (i
= 0; i
< C
->NbRows
; ++i
) {
337 negated_sum(C
->p
[i
]+1, nvar
, inflate
, &sum
);
338 value_addto(C
->p
[i
][1+P
->Dimension
], C
->p
[i
][1+P
->Dimension
], sum
);
341 P2
= Constraints2Polyhedron(C
, MaxRays
);
346 C
= Polyhedron_Project(P
, nparam
);
347 CA
= align_context(C
, P
->Dimension
, MaxRays
);
349 P2
= DomainIntersection(P
, CA
, MaxRays
);
358 static Polyhedron
*flate_narrow2(Polyhedron
*P
, Lattice
*L
,
359 unsigned nparam
, int inflate
,
363 unsigned nvar
= P
->Dimension
- nparam
;
369 expansion
= Matrix_Alloc(nvar
+ nparam
+ 1, nvar
+ nparam
+ 1);
370 for (i
= 0; i
< nvar
; ++i
)
371 Vector_Copy(L
->p
[i
], expansion
->p
[i
], nvar
);
372 for (i
= nvar
; i
< nvar
+nparam
+1; ++i
)
373 value_assign(expansion
->p
[i
][i
], L
->p
[nvar
][nvar
]);
375 C
= Matrix_Alloc(P
->NbConstraints
+1, 1+P
->Dimension
+1);
377 for (i
= 0; i
< P
->NbConstraints
; ++i
) {
378 negated_sum(P
->Constraint
[i
]+1, nvar
, inflate
, &sum
);
379 value_assign(C
->p
[i
][0], P
->Constraint
[i
][0]);
380 Vector_Matrix_Product(P
->Constraint
[i
]+1, expansion
, C
->p
[i
]+1);
381 if (value_zero_p(sum
))
383 Vector_Copy(C
->p
[i
]+1, C
->p
[i
+1]+1, P
->Dimension
+1);
384 value_addmul(C
->p
[i
][1+P
->Dimension
], sum
, L
->p
[nvar
][nvar
]);
385 ConstraintSimplify(C
->p
[i
], C
->p
[i
], P
->Dimension
+2, &sum
);
386 ConstraintSimplify(C
->p
[i
+1], C
->p
[i
+1], P
->Dimension
+2, &sum
);
387 if (value_ne(C
->p
[i
][1+P
->Dimension
], C
->p
[i
+1][1+P
->Dimension
])) {
389 value_decrement(C
->p
[i
][1+P
->Dimension
], C
->p
[i
][1+P
->Dimension
]);
391 value_increment(C
->p
[i
][1+P
->Dimension
], C
->p
[i
][1+P
->Dimension
]);
396 P2
= Constraints2Polyhedron(C
, MaxRays
);
399 Matrix_Free(expansion
);
403 C
= Polyhedron_Project(P
, nparam
);
404 CA
= align_context(C
, P
->Dimension
, MaxRays
);
406 P2
= DomainIntersection(P
, CA
, MaxRays
);
415 static void linear_min(Polyhedron
*D
, Value
*obj
, Value
*min
)
420 POL_ENSURE_VERTICES(D
);
421 for (i
= 0; i
< D
->NbRays
; ++i
) {
422 Inner_Product(obj
, D
->Ray
[i
]+1, D
->Dimension
, &tmp
);
423 mpz_cdiv_q(tmp
, tmp
, D
->Ray
[i
][1+D
->Dimension
]);
424 if (!i
|| value_lt(tmp
, *min
))
425 value_assign(*min
, tmp
);
430 static Polyhedron
*inflate_deflate_domain(Lattice
*L
, unsigned MaxRays
)
432 unsigned nvar
= L
->NbRows
-1;
437 M
= Matrix_Alloc(2*nvar
, 1+nvar
+1);
438 for (i
= 0; i
< nvar
; ++i
) {
439 value_set_si(M
->p
[2*i
][0], 1);
440 Vector_Copy(L
->p
[i
], M
->p
[2*i
]+1, nvar
);
441 Vector_Normalize(M
->p
[2*i
]+1, nvar
);
443 value_set_si(M
->p
[2*i
+1][0], 1);
444 Vector_Oppose(L
->p
[i
], M
->p
[2*i
+1]+1, nvar
);
445 value_assign(M
->p
[2*i
+1][1+nvar
], L
->p
[nvar
][nvar
]);
446 Vector_Normalize(M
->p
[2*i
+1]+1, nvar
+1);
447 value_decrement(M
->p
[2*i
+1][1+nvar
], M
->p
[2*i
+1][1+nvar
]);
449 D
= Constraints2Polyhedron(M
, MaxRays
);
455 static Polyhedron
*flate_narrow(Polyhedron
*P
, Lattice
*L
,
456 unsigned nparam
, int inflate
, unsigned MaxRays
)
459 unsigned nvar
= P
->Dimension
- nparam
;
466 D
= inflate_deflate_domain(L
, MaxRays
);
468 obj
= Vector_Alloc(nvar
);
469 C
= Polyhedron2Constraints(P
);
471 for (i
= 0; i
< C
->NbRows
; ++i
) {
473 Vector_Copy(C
->p
[i
]+1, obj
->p
, nvar
);
475 Vector_Oppose(C
->p
[i
]+1, obj
->p
, nvar
);
476 linear_min(D
, obj
->p
, &min
);
478 value_subtract(C
->p
[i
][1+P
->Dimension
], C
->p
[i
][1+P
->Dimension
], min
);
480 value_addto(C
->p
[i
][1+P
->Dimension
], C
->p
[i
][1+P
->Dimension
], min
);
484 P2
= Constraints2Polyhedron(C
, MaxRays
);
491 C
= Polyhedron_Project(P
, nparam
);
492 CA
= align_context(C
, P
->Dimension
, MaxRays
);
494 P2
= DomainIntersection(P
, CA
, MaxRays
);
503 static Polyhedron
*flate(Polyhedron
*P
, Lattice
*L
,
504 unsigned nparam
, int inflate
,
505 struct barvinok_options
*options
)
507 if (options
->approx
->scale_flags
& BV_APPROX_SCALE_NARROW2
)
508 return flate_narrow2(P
, L
, nparam
, inflate
, options
->MaxRays
);
509 else if (options
->approx
->scale_flags
& BV_APPROX_SCALE_NARROW
)
510 return flate_narrow(P
, L
, nparam
, inflate
, options
->MaxRays
);
512 return Polyhedron_Flate(P
, nparam
, inflate
, options
->MaxRays
);
515 static void Param_Polyhedron_Scale(Param_Polyhedron
*PP
, Lattice
**L
,
516 Value
*det
, struct barvinok_options
*options
)
518 if (options
->approx
->scale_flags
& BV_APPROX_SCALE_FAST
)
519 Param_Polyhedron_Scale_Integer_Fast(PP
, L
, det
, options
->MaxRays
);
521 Param_Polyhedron_Scale_Integer_Slow(PP
, L
, det
, options
->MaxRays
);
524 static evalue
*enumerate_flated(Polyhedron
*P
, Polyhedron
*C
, Lattice
*L
,
525 struct barvinok_options
*options
)
527 unsigned nparam
= C
->Dimension
;
529 int save_approximation
= options
->approx
->approximation
;
531 if (options
->approx
->approximation
== BV_APPROX_SIGN_UPPER
)
532 P
= flate(P
, L
, nparam
, 1, options
);
533 if (options
->approx
->approximation
== BV_APPROX_SIGN_LOWER
)
534 P
= flate(P
, L
, nparam
, 0, options
);
536 /* Don't deflate/inflate again (on this polytope) */
537 options
->approx
->approximation
= BV_APPROX_SIGN_NONE
;
538 eres
= barvinok_enumerate_with_options(P
, C
, options
);
539 options
->approx
->approximation
= save_approximation
;
545 static evalue
*PP_enumerate_narrow_flated(Param_Polyhedron
*PP
,
546 Polyhedron
*P
, Polyhedron
*C
,
547 struct barvinok_options
*options
)
549 Polyhedron
*Porig
= P
;
550 int scale_narrow2
= options
->approx
->scale_flags
& BV_APPROX_SCALE_NARROW2
;
556 value_set_si(det
, 1);
558 Param_Polyhedron_Scale(PP
, &L
, &det
, options
);
560 P
= Param_Polyhedron2Polyhedron(PP
, options
);
561 Param_Polyhedron_Free(PP
);
562 /* Don't scale again (on this polytope) */
563 options
->approx
->method
= BV_APPROX_NONE
;
564 eres
= enumerate_flated(P
, C
, L
, options
);
565 options
->approx
->method
= BV_APPROX_SCALE
;
569 if (value_notone_p(det
))
570 evalue_div(eres
, det
);
575 #define INT_BITS (sizeof(unsigned) * 8)
577 static Param_Polyhedron
*Param_Polyhedron_Domain(Param_Polyhedron
*PP
,
582 Param_Polyhedron
*PP_D
;
585 Param_Vertices
**next
, *V
;
586 int facet_len
= (PP
->Constraints
->NbRows
+INT_BITS
-1)/INT_BITS
;
588 PP_D
= ALLOC(Param_Polyhedron
);
589 PP_D
->D
= ALLOC(Param_Domain
);
590 PP_D
->D
->next
= NULL
;
591 PP_D
->D
->Domain
= Domain_Copy(rVD
);
593 PP_D
->Constraints
= Matrix_Copy(PP
->Constraints
);
596 nv
= (PP
->nbV
- 1)/(8*sizeof(int)) + 1;
597 PP_D
->D
->F
= ALLOCN(unsigned, nv
);
598 memset(PP_D
->D
->F
, 0, nv
* sizeof(unsigned));
604 FORALL_PVertex_in_ParamPolyhedron(V
, D
, PP
)
605 Param_Vertices
*V2
= ALLOC(Param_Vertices
);
606 V2
->Vertex
= Matrix_Copy(V
->Vertex
);
611 V2
->Facets
= ALLOCN(unsigned, facet_len
);
612 memcpy(V2
->Facets
, V
->Facets
, facet_len
* sizeof(unsigned));
616 PP_D
->D
->F
[ix
] |= bx
;
619 END_FORALL_PVertex_in_ParamPolyhedron
;
625 static evalue
*enumerate_narrow_flated(Polyhedron
*P
, Polyhedron
*C
,
626 struct barvinok_options
*options
)
628 unsigned Rat_MaxRays
= options
->MaxRays
;
629 Param_Polyhedron
*PP
;
630 PP
= Polyhedron2Param_Polyhedron(P
, C
, options
);
631 POL_UNSET(Rat_MaxRays
, POL_INTEGER
);
633 if ((options
->approx
->scale_flags
& BV_APPROX_SCALE_CHAMBER
) && PP
->D
->next
) {
635 evalue
*tmp
, *eres
= NULL
;
636 Polyhedron
*TC
= true_context(P
, C
, options
->MaxRays
);
638 FORALL_REDUCED_DOMAIN(PP
, TC
, nd
, options
, i
, D
, rVD
)
640 Param_Polyhedron
*PP_D
;
641 /* Intersect with D->Domain, so we only have the relevant constraints
642 * left. Don't use rVD, though, since we still want to recognize
643 * the defining constraints of the parametric vertices.
645 CA
= align_context(D
->Domain
, P
->Dimension
, options
->MaxRays
);
646 P2
= DomainIntersection(P
, CA
, Rat_MaxRays
);
647 POL_ENSURE_VERTICES(P2
);
649 /* Use rVD for context, to avoid overlapping domains in
650 * results of computations in different chambers.
652 PP_D
= Param_Polyhedron_Domain(PP
, D
, rVD
);
653 tmp
= PP_enumerate_narrow_flated(PP_D
, P2
, rVD
, options
);
659 free_evalue_refs(tmp
);
662 Polyhedron_Free(rVD
);
663 END_FORALL_REDUCED_DOMAIN
664 Param_Polyhedron_Free(PP
);
666 eres
= evalue_zero();
670 return PP_enumerate_narrow_flated(PP
, P
, C
, options
);
673 /* If scaling is to be performed in combination with deflation/inflation,
674 * do both and return the result.
675 * Otherwise return NULL.
677 evalue
*scale_bound(Polyhedron
*P
, Polyhedron
*C
,
678 struct barvinok_options
*options
)
680 int scale_narrow
= options
->approx
->scale_flags
& BV_APPROX_SCALE_NARROW
;
681 int scale_narrow2
= options
->approx
->scale_flags
& BV_APPROX_SCALE_NARROW2
;
683 if (options
->approx
->approximation
== BV_APPROX_SIGN_NONE
||
684 options
->approx
->approximation
== BV_APPROX_SIGN_APPROX
)
687 if (scale_narrow
|| scale_narrow2
)
688 return enumerate_narrow_flated(P
, C
, options
);
690 return enumerate_flated(P
, C
, NULL
, options
);
693 evalue
*scale(Param_Polyhedron
*PP
, Polyhedron
*P
, Polyhedron
*C
,
694 struct barvinok_options
*options
)
701 if ((options
->approx
->scale_flags
& BV_APPROX_SCALE_CHAMBER
) && PP
->D
->next
) {
704 Polyhedron
*TC
= true_context(P
, C
, options
->MaxRays
);
706 FORALL_REDUCED_DOMAIN(PP
, TC
, nd
, options
, i
, D
, rVD
)
707 Param_Polyhedron
*PP_D
= Param_Polyhedron_Domain(PP
, D
, rVD
);
708 tmp
= scale(PP_D
, P
, rVD
, options
);
713 free_evalue_refs(tmp
);
716 Param_Polyhedron_Free(PP_D
);
717 Polyhedron_Free(rVD
);
718 END_FORALL_REDUCED_DOMAIN
720 eres
= evalue_zero();
726 value_set_si(det
, 1);
728 MaxRays
= options
->MaxRays
;
729 POL_UNSET(options
->MaxRays
, POL_INTEGER
);
730 Param_Polyhedron_Scale(PP
, NULL
, &det
, options
);
731 options
->MaxRays
= MaxRays
;
733 T
= Param_Polyhedron2Polyhedron(PP
, options
);
734 eres
= Param_Polyhedron_Enumerate(PP
, T
, C
, options
);
737 if (value_notone_p(det
))
738 evalue_div(eres
, det
);