3 #include <bernstein/bernstein.h>
4 #include <bernstein/piecewise_lst.h>
5 #include <isl_set_polylib.h>
6 #include <barvinok/barvinok.h>
7 #include <barvinok/util.h>
8 #include <barvinok/bernstein.h>
9 #include <barvinok/options.h>
10 #include "bound_common.h"
11 #include "reduce_domain.h"
13 using namespace GiNaC
;
14 using namespace bernstein
;
15 using namespace barvinok
;
24 ex
evalue2ex(evalue
*e
, const exvector
& vars
)
26 if (value_pos_p(e
->d
))
27 return value2numeric(e
->x
.n
)/value2numeric(e
->d
);
28 if (EVALUE_IS_NAN(*e
))
30 if (e
->x
.p
->type
!= polynomial
)
33 for (int i
= e
->x
.p
->size
-1; i
>= 0; --i
) {
34 poly
*= vars
[e
->x
.p
->pos
-1];
35 ex t
= evalue2ex(&e
->x
.p
->arr
[i
], vars
);
36 if (is_exactly_a
<fail
>(t
))
43 static int type_offset(enode
*p
)
45 return p
->type
== fractional
? 1 :
46 p
->type
== flooring
? 1 : 0;
49 typedef pair
<bool, const evalue
*> typed_evalue
;
51 static ex
evalue2ex_add_var(evalue
*e
, exvector
& extravar
,
52 vector
<typed_evalue
>& expr
, bool is_fract
)
56 for (int i
= 0; i
< expr
.size(); ++i
) {
57 if (is_fract
== expr
[i
].first
&& eequal(e
, expr
[i
].second
)) {
58 base_var
= extravar
[i
];
66 snprintf(name
, sizeof(name
), "f%c%zd", is_fract
? 'r' : 'l', expr
.size());
67 extravar
.push_back(base_var
= symbol(name
));
68 expr
.push_back(typed_evalue(is_fract
, e
));
73 /* For the argument e=(f/d) of a fractional, return (d-1)/d times
74 * a variable in [0,1] (see setup_constraints).
76 static ex
evalue2ex_get_fract(evalue
*e
, exvector
& extravar
,
77 vector
<typed_evalue
>& expr
)
85 den
= value2numeric(d
);
89 ex base_var
= evalue2ex_add_var(e
, extravar
, expr
, true);
94 static ex
evalue2ex_r(const evalue
*e
, const exvector
& vars
,
95 exvector
& extravar
, vector
<typed_evalue
>& expr
,
98 if (value_notzero_p(e
->d
))
99 return value2numeric(e
->x
.n
)/value2numeric(e
->d
);
104 switch (e
->x
.p
->type
) {
106 base_var
= vars
[e
->x
.p
->pos
-1];
109 base_var
= evalue2ex_add_var(&e
->x
.p
->arr
[0], extravar
, expr
, false);
112 base_var
= evalue2ex_get_fract(&e
->x
.p
->arr
[0], extravar
, expr
);
116 rem
= VALUE_TO_INT(coset
->p
[e
->x
.p
->pos
-1]) % e
->x
.p
->size
;
117 return evalue2ex_r(&e
->x
.p
->arr
[rem
], vars
, extravar
, expr
, coset
);
122 int offset
= type_offset(e
->x
.p
);
123 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
125 ex t
= evalue2ex_r(&e
->x
.p
->arr
[i
], vars
, extravar
, expr
, coset
);
126 if (is_exactly_a
<fail
>(t
))
133 /* For each t = floor(e/d), set up two constraints
136 * -e + d t + d-1 >= 0
138 * e is assumed to be an affine expression.
140 * For each t = fract(e/d), set up two constraints
145 static Matrix
*setup_constraints(const vector
<typed_evalue
> expr
, int nvar
)
147 int extra
= expr
.size();
150 Matrix
*M
= Matrix_Alloc(2*extra
, 1+extra
+nvar
+1);
151 for (int i
= 0; i
< extra
; ++i
) {
153 value_set_si(M
->p
[2*i
][0], 1);
154 value_set_si(M
->p
[2*i
][1+i
], -1);
155 value_set_si(M
->p
[2*i
][1+extra
+nvar
], 1);
156 value_set_si(M
->p
[2*i
+1][0], 1);
157 value_set_si(M
->p
[2*i
+1][1+i
], 1);
159 Value
*d
= &M
->p
[2*i
][1+i
];
160 evalue_extract_affine(expr
[i
].second
, M
->p
[2*i
]+1+extra
,
161 M
->p
[2*i
]+1+extra
+nvar
, d
);
162 value_oppose(*d
, *d
);
163 value_set_si(M
->p
[2*i
][0], -1);
164 Vector_Scale(M
->p
[2*i
], M
->p
[2*i
+1], M
->p
[2*i
][0], 1+extra
+nvar
+1);
165 value_set_si(M
->p
[2*i
][0], 1);
166 value_subtract(M
->p
[2*i
+1][1+extra
+nvar
], M
->p
[2*i
+1][1+extra
+nvar
], *d
);
167 value_decrement(M
->p
[2*i
+1][1+extra
+nvar
], M
->p
[2*i
+1][1+extra
+nvar
]);
173 static bool evalue_is_periodic(const evalue
*e
, Vector
*periods
)
176 bool is_periodic
= false;
178 if (value_notzero_p(e
->d
))
181 assert(e
->x
.p
->type
!= partition
);
182 if (e
->x
.p
->type
== periodic
) {
185 value_set_si(size
, e
->x
.p
->size
);
186 value_lcm(periods
->p
[e
->x
.p
->pos
-1], periods
->p
[e
->x
.p
->pos
-1], size
);
190 offset
= type_offset(e
->x
.p
);
191 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
192 is_periodic
= evalue_is_periodic(&e
->x
.p
->arr
[i
], periods
) || is_periodic
;
196 static ex
evalue2lst(const evalue
*e
, const exvector
& vars
,
197 exvector
& extravar
, vector
<typed_evalue
>& expr
,
200 Vector
*coset
= Vector_Alloc(periods
->Size
);
204 list
.append(evalue2ex_r(e
, vars
, extravar
, expr
, coset
));
205 for (i
= coset
->Size
-1; i
>= 0; --i
) {
206 value_increment(coset
->p
[i
], coset
->p
[i
]);
207 if (value_lt(coset
->p
[i
], periods
->p
[i
]))
209 value_set_si(coset
->p
[i
], 0);
218 ex
evalue2ex(const evalue
*e
, const exvector
& vars
, exvector
& floorvar
,
219 Matrix
**C
, Vector
**p
)
221 vector
<typed_evalue
> expr
;
222 Vector
*periods
= Vector_Alloc(vars
.size());
225 for (int i
= 0; i
< periods
->Size
; ++i
)
226 value_set_si(periods
->p
[i
], 1);
227 if (evalue_is_periodic(e
, periods
)) {
233 Vector_Free(periods
);
235 ex poly
= evalue2ex_r(e
, vars
, floorvar
, expr
, NULL
);
236 Matrix
*M
= setup_constraints(expr
, vars
.size());
242 /* if the evalue is a relation, we use the relation to cut off the
243 * the edges of the domain
245 static Polyhedron
*relation_domain(Polyhedron
*D
, evalue
*fr
, unsigned MaxRays
)
247 assert(value_zero_p(fr
->d
));
248 assert(fr
->x
.p
->type
== fractional
);
249 assert(fr
->x
.p
->size
== 3);
250 Matrix
*T
= Matrix_Alloc(2, D
->Dimension
+1);
251 value_set_si(T
->p
[1][D
->Dimension
], 1);
253 /* convert argument of fractional to polylib */
254 /* the argument is assumed to be linear */
255 evalue
*p
= &fr
->x
.p
->arr
[0];
256 evalue_denom(p
, &T
->p
[1][D
->Dimension
]);
257 for (;value_zero_p(p
->d
); p
= &p
->x
.p
->arr
[0]) {
258 assert(p
->x
.p
->type
== polynomial
);
259 assert(p
->x
.p
->size
== 2);
260 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
261 int pos
= p
->x
.p
->pos
- 1;
262 value_assign(T
->p
[0][pos
], p
->x
.p
->arr
[1].x
.n
);
263 value_multiply(T
->p
[0][pos
], T
->p
[0][pos
], T
->p
[1][D
->Dimension
]);
264 value_division(T
->p
[0][pos
], T
->p
[0][pos
], p
->x
.p
->arr
[1].d
);
266 int pos
= D
->Dimension
;
267 value_assign(T
->p
[0][pos
], p
->x
.n
);
268 value_multiply(T
->p
[0][pos
], T
->p
[0][pos
], T
->p
[1][D
->Dimension
]);
269 value_division(T
->p
[0][pos
], T
->p
[0][pos
], p
->d
);
271 Polyhedron
*E
= NULL
;
272 for (Polyhedron
*P
= D
; P
; P
= P
->next
) {
273 Polyhedron
*I
= Polyhedron_Image(P
, T
, MaxRays
);
274 I
= DomainConstraintSimplify(I
, MaxRays
);
275 Polyhedron
*R
= Polyhedron_Preimage(I
, T
, MaxRays
);
277 Polyhedron
*next
= P
->next
;
279 Polyhedron
*S
= DomainIntersection(P
, R
, MaxRays
);
285 E
= DomainConcat(S
, E
);
292 piecewise_lst
*evalue_bernstein_coefficients(piecewise_lst
*pl_all
, evalue
*e
,
293 Polyhedron
*ctx
, const exvector
& params
)
296 barvinok_options
*options
= barvinok_options_new_with_defaults();
297 pl
= evalue_bernstein_coefficients(pl_all
, e
, ctx
, params
, options
);
298 barvinok_options_free(options
);
302 static piecewise_lst
*bernstein_coefficients(piecewise_lst
*pl_all
,
303 Polyhedron
*D
, const ex
& poly
,
305 const exvector
& params
, const exvector
& floorvar
,
306 barvinok_options
*options
);
308 /* Recursively apply Bernstein expansion on P, optimizing over dims[i]
309 * variables in each level. The context ctx is assumed to have been adapted
310 * to the first level in the recursion.
312 static piecewise_lst
*bernstein_coefficients_recursive(piecewise_lst
*pl_all
,
313 Polyhedron
*P
, const vector
<int>& dims
, const ex
& poly
,
315 const exvector
& params
, const exvector
& vars
,
316 barvinok_options
*options
)
318 assert(dims
.size() > 0);
319 assert(ctx
->Dimension
== P
->Dimension
- dims
[0]);
322 for (int j
= 0; j
< dims
.size(); ++j
) {
324 pl_vars
.insert(pl_vars
.end(), vars
.begin()+done
, vars
.begin()+done
+dims
[j
]);
326 pl_params
.insert(pl_params
.end(), vars
.begin()+done
+dims
[j
], vars
.end());
327 pl_params
.insert(pl_params
.end(), params
.begin(), params
.end());
330 pl
= bernstein_coefficients(NULL
, P
, poly
, ctx
,
331 pl_params
, pl_vars
, options
);
333 piecewise_lst
*new_pl
= NULL
;
334 Polyhedron
*U
= Universe_Polyhedron(pl_params
.size());
336 for (int i
= 0; i
< pl
->list
.size(); ++i
) {
337 Polyhedron
*D
= pl
->list
[i
].first
;
338 lst polys
= pl
->list
[i
].second
;
339 new_pl
= bernstein_coefficients(new_pl
, D
, polys
, U
, pl_params
,
358 pl_all
->combine(*pl
);
365 static piecewise_lst
*bernstein_coefficients_full_recurse(piecewise_lst
*pl_all
,
366 Polyhedron
*P
, const ex
& poly
,
368 const exvector
& params
, const exvector
& vars
,
369 barvinok_options
*options
)
371 Polyhedron
*CR
= align_context(ctx
, P
->Dimension
-1, options
->MaxRays
);
372 vector
<int> dims(vars
.size());
373 for (int i
= 0; i
< dims
.size(); ++i
)
375 pl_all
= bernstein_coefficients_recursive(pl_all
, P
, dims
, poly
, CR
,
376 params
, vars
, options
);
382 static piecewise_lst
*bernstein_coefficients_product(piecewise_lst
*pl_all
,
383 Polyhedron
*F
, Matrix
*T
, const ex
& poly
,
385 const exvector
& params
, const exvector
& vars
,
386 barvinok_options
*options
)
390 for (Polyhedron
*G
= F
; G
; G
= G
->next
)
394 unsigned nparam
= params
.size();
395 unsigned nvar
= vars
.size();
396 unsigned constraints
;
398 Polyhedron
*C
= NULL
;
400 /* More context constraints */
401 if (F
->Dimension
== ctx
->Dimension
) {
411 M
= Matrix_Alloc(F
->NbConstraints
, 1+nvar
+nparam
+1);
412 for (int i
= 0; i
< F
->NbConstraints
; ++i
) {
413 Vector_Copy(F
->Constraint
[i
], M
->p
[i
], 1+F
->Dimension
-nparam
);
414 Vector_Copy(F
->Constraint
[i
]+1+F
->Dimension
-nparam
,
415 M
->p
[i
]+1+nvar
, nparam
+1);
417 P
= Constraints2Polyhedron(M
, options
->MaxRays
);
421 constraints
= C
? C
->NbConstraints
: 0;
422 constraints
+= ctx
->NbConstraints
;
423 for (Polyhedron
*G
= F
->next
; G
; G
= G
->next
) {
424 constraints
+= G
->NbConstraints
;
428 unsigned total_var
= nvar
-(F
->Dimension
-nparam
);
431 M
= Matrix_Alloc(constraints
, 1+total_var
+nparam
+1);
432 for (Polyhedron
*G
= F
->next
; G
; G
= G
->next
) {
433 unsigned this_var
= G
->Dimension
- nparam
;
434 for (int i
= 0; i
< G
->NbConstraints
; ++i
) {
435 value_assign(M
->p
[c
+i
][0], G
->Constraint
[i
][0]);
436 Vector_Copy(G
->Constraint
[i
]+1, M
->p
[c
+i
]+1+skip
, this_var
);
437 Vector_Copy(G
->Constraint
[i
]+1+this_var
, M
->p
[c
+i
]+1+total_var
,
440 c
+= G
->NbConstraints
;
443 assert(skip
== total_var
);
445 for (int i
= 0; i
< C
->NbConstraints
; ++i
) {
446 value_assign(M
->p
[c
+i
][0], C
->Constraint
[i
][0]);
447 Vector_Copy(C
->Constraint
[i
]+1, M
->p
[c
+i
]+1+total_var
,
450 c
+= C
->NbConstraints
;
452 for (int i
= 0; i
< ctx
->NbConstraints
; ++i
) {
453 value_assign(M
->p
[c
+i
][0], ctx
->Constraint
[i
][0]);
454 Vector_Copy(ctx
->Constraint
[i
]+1, M
->p
[c
+i
]+1+total_var
, nparam
+1);
456 PC
= Constraints2Polyhedron(M
, options
->MaxRays
);
459 exvector newvars
= constructVariableVector(nvar
, "t");
460 matrix
subs(1, nvar
);
461 for (int i
= 0; i
< nvar
; ++i
)
462 for (int j
= 0; j
< nvar
; ++j
)
463 subs(0,i
) += value2numeric(T
->p
[i
][j
]) * newvars
[j
];
465 ex newpoly
= replaceVariablesInPolynomial(poly
, vars
, subs
);
467 vector
<int> dims(factors
);
468 for (int i
= 0; F
; ++i
, F
= F
->next
)
469 dims
[i
] = F
->Dimension
-nparam
;
471 pl_all
= bernstein_coefficients_recursive(pl_all
, P
, dims
, newpoly
, PC
,
472 params
, newvars
, options
);
480 static piecewise_lst
*bernstein_coefficients_polyhedron(piecewise_lst
*pl_all
,
481 Polyhedron
*P
, const ex
& poly
,
483 const exvector
& params
, const exvector
& floorvar
,
484 barvinok_options
*options
)
486 if (Polyhedron_is_unbounded(P
, ctx
->Dimension
, options
->MaxRays
)) {
487 fprintf(stderr
, "warning: unbounded domain skipped\n");
488 Polyhedron_Print(stderr
, P_VALUE_FMT
, P
);
492 if (options
->bernstein_recurse
& BV_BERNSTEIN_FACTORS
) {
494 Polyhedron
*F
= Polyhedron_Factor(P
, ctx
->Dimension
, &T
, options
->MaxRays
);
496 pl_all
= bernstein_coefficients_product(pl_all
, F
, T
, poly
, ctx
, params
,
503 if (floorvar
.size() > 1 &&
504 options
->bernstein_recurse
& BV_BERNSTEIN_INTERVALS
)
505 return bernstein_coefficients_full_recurse(pl_all
, P
, poly
, ctx
,
506 params
, floorvar
, options
);
508 unsigned PP_MaxRays
= options
->MaxRays
;
509 if (PP_MaxRays
& POL_NO_DUAL
)
512 Param_Polyhedron
*PP
= Polyhedron2Param_Domain(P
, ctx
, PP_MaxRays
);
515 piecewise_lst
*pl
= new piecewise_lst(params
, options
->bernstein_optimize
);
518 Polyhedron
*TC
= true_context(P
, ctx
, options
->MaxRays
);
519 FORALL_REDUCED_DOMAIN(PP
, TC
, nd
, options
, i
, PD
, rVD
)
520 matrix VM
= domainVertices(PP
, PD
, params
);
521 lst coeffs
= bernsteinExpansion(VM
, poly
, floorvar
, params
);
522 pl
->add_guarded_lst(rVD
, coeffs
);
523 END_FORALL_REDUCED_DOMAIN
526 Param_Polyhedron_Free(PP
);
530 pl_all
->combine(*pl
);
537 static piecewise_lst
*bernstein_coefficients(piecewise_lst
*pl_all
,
538 Polyhedron
*D
, const ex
& poly
,
540 const exvector
& params
, const exvector
& floorvar
,
541 barvinok_options
*options
)
543 if (!D
->next
&& emptyQ2(D
))
546 for (Polyhedron
*P
= D
; P
; P
= P
->next
) {
547 /* This shouldn't happen */
550 Polyhedron
*next
= P
->next
;
552 pl_all
= bernstein_coefficients_polyhedron(pl_all
, P
, poly
, ctx
,
553 params
, floorvar
, options
);
559 /* Compute the coefficients of the polynomial corresponding to each coset
560 * on its own domain. This allows us to cut the domain on multiples of
562 * To perform the cutting for a coset "i mod n = c" we map the domain
563 * to the quotient space trough "i = i' n + c", simplify the constraints
564 * (implicitly) and then map back to the original space.
566 static piecewise_lst
*bernstein_coefficients_periodic(piecewise_lst
*pl_all
,
567 Polyhedron
*D
, const evalue
*e
,
568 Polyhedron
*ctx
, const exvector
& vars
,
569 const exvector
& params
, Vector
*periods
,
570 barvinok_options
*options
)
572 assert(D
->Dimension
== periods
->Size
);
573 Matrix
*T
= Matrix_Alloc(D
->Dimension
+1, D
->Dimension
+1);
574 Matrix
*T2
= Matrix_Alloc(D
->Dimension
+1, D
->Dimension
+1);
575 Vector
*coset
= Vector_Alloc(periods
->Size
);
577 vector
<typed_evalue
> expr
;
578 exvector allvars
= vars
;
579 allvars
.insert(allvars
.end(), params
.begin(), params
.end());
581 value_set_si(T2
->p
[D
->Dimension
][D
->Dimension
], 1);
582 for (int i
= 0; i
< D
->Dimension
; ++i
) {
583 value_assign(T
->p
[i
][i
], periods
->p
[i
]);
584 value_lcm(T2
->p
[D
->Dimension
][D
->Dimension
],
585 T2
->p
[D
->Dimension
][D
->Dimension
], periods
->p
[i
]);
587 value_set_si(T
->p
[D
->Dimension
][D
->Dimension
], 1);
588 for (int i
= 0; i
< D
->Dimension
; ++i
)
589 value_division(T2
->p
[i
][i
], T2
->p
[D
->Dimension
][D
->Dimension
],
593 ex poly
= evalue2ex_r(e
, allvars
, extravar
, expr
, coset
);
594 assert(extravar
.size() == 0);
595 assert(expr
.size() == 0);
596 Polyhedron
*E
= DomainPreimage(D
, T
, options
->MaxRays
);
597 Polyhedron
*F
= DomainPreimage(E
, T2
, options
->MaxRays
);
600 pl_all
= bernstein_coefficients(pl_all
, F
, poly
, ctx
, params
,
603 for (i
= D
->Dimension
-1; i
>= 0; --i
) {
604 value_increment(coset
->p
[i
], coset
->p
[i
]);
605 value_increment(T
->p
[i
][D
->Dimension
], T
->p
[i
][D
->Dimension
]);
606 value_subtract(T2
->p
[i
][D
->Dimension
], T2
->p
[i
][D
->Dimension
],
608 if (value_lt(coset
->p
[i
], periods
->p
[i
]))
610 value_set_si(coset
->p
[i
], 0);
611 value_set_si(T
->p
[i
][D
->Dimension
], 0);
612 value_set_si(T2
->p
[i
][D
->Dimension
], 0);
623 piecewise_lst
*bernstein_coefficients_relation(piecewise_lst
*pl_all
,
624 Polyhedron
*D
, evalue
*EP
, Polyhedron
*ctx
,
625 const exvector
& allvars
, const exvector
& vars
,
626 const exvector
& params
, barvinok_options
*options
)
628 if (value_zero_p(EP
->d
) && EP
->x
.p
->type
== relation
) {
629 Polyhedron
*E
= relation_domain(D
, &EP
->x
.p
->arr
[0], options
->MaxRays
);
631 pl_all
= bernstein_coefficients_relation(pl_all
, E
, &EP
->x
.p
->arr
[1],
632 ctx
, allvars
, vars
, params
,
636 /* In principle, we could cut off the edges of this domain too */
637 if (EP
->x
.p
->size
> 2)
638 pl_all
= bernstein_coefficients_relation(pl_all
, D
, &EP
->x
.p
->arr
[2],
639 ctx
, allvars
, vars
, params
,
647 ex poly
= evalue2ex(EP
, allvars
, floorvar
, &M
, &periods
);
648 floorvar
.insert(floorvar
.end(), vars
.begin(), vars
.end());
651 Polyhedron
*AE
= align_context(D
, M
->NbColumns
-2, options
->MaxRays
);
652 E
= DomainAddConstraints(AE
, M
, options
->MaxRays
);
656 if (is_exactly_a
<fail
>(poly
)) {
661 pl_all
= bernstein_coefficients_periodic(pl_all
, E
, EP
, ctx
, vars
,
662 params
, periods
, options
);
664 pl_all
= bernstein_coefficients(pl_all
, E
, poly
, ctx
, params
,
667 Vector_Free(periods
);
674 piecewise_lst
*evalue_bernstein_coefficients(piecewise_lst
*pl_all
, evalue
*e
,
675 Polyhedron
*ctx
, const exvector
& params
,
676 barvinok_options
*options
)
678 unsigned nparam
= ctx
->Dimension
;
679 if (EVALUE_IS_ZERO(*e
))
681 assert(value_zero_p(e
->d
));
682 assert(e
->x
.p
->type
== partition
);
683 assert(e
->x
.p
->size
>= 2);
684 unsigned nvars
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
- nparam
;
686 exvector vars
= constructVariableVector(nvars
, "v");
687 exvector allvars
= vars
;
688 allvars
.insert(allvars
.end(), params
.begin(), params
.end());
690 for (int i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
691 pl_all
= bernstein_coefficients_relation(pl_all
,
692 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), &e
->x
.p
->arr
[2*i
+1],
693 ctx
, allvars
, vars
, params
, options
);
698 static __isl_give isl_qpolynomial
*qp_from_ex(__isl_take isl_dim
*dim
,
699 const GiNaC::ex ex
, const GiNaC::exvector
¶ms
, int i
)
702 isl_qpolynomial
*base
;
707 return isl_qpolynomial_nan(dim
);
709 if (is_a
<numeric
>(ex
)) {
710 numeric r
= ex_to
<numeric
>(ex
);
715 numeric2value(r
.numer(), n
);
716 numeric2value(r
.denom(), d
);
717 qp
= isl_qpolynomial_rat_cst(dim
, n
, d
);
723 deg
= ex
.degree(params
[i
]);
725 return qp_from_ex(dim
, ex
, params
, i
+ 1);
727 base
= isl_qpolynomial_var(isl_dim_copy(dim
), isl_dim_param
, i
);
728 qp
= qp_from_ex(isl_dim_copy(dim
), ex
.coeff(params
[i
], deg
),
731 for (j
= deg
- 1; j
>= 0; --j
) {
732 qp
= isl_qpolynomial_mul(qp
, isl_qpolynomial_copy(base
));
733 qp
= isl_qpolynomial_add(qp
,
734 qp_from_ex(isl_dim_copy(dim
), ex
.coeff(params
[i
], j
),
738 isl_qpolynomial_free(base
);
744 __isl_give isl_qpolynomial
*isl_qpolynomial_from_ginac(__isl_take isl_dim
*dim
,
745 const GiNaC::ex
&ex
, const GiNaC::exvector
¶ms
)
753 return qp_from_ex(dim
, exp
, params
, 0);
759 __isl_give isl_qpolynomial_fold
*isl_qpolynomial_fold_from_ginac(
760 __isl_take isl_dim
*dim
, enum isl_fold type
, const GiNaC::lst
&lst
,
761 const GiNaC::exvector
¶ms
)
763 isl_qpolynomial_fold
*fold
;
764 lst::const_iterator j
;
766 fold
= isl_qpolynomial_fold_empty(type
, isl_dim_copy(dim
));
767 for (j
= lst
.begin(); j
!= lst
.end(); ++j
) {
769 isl_qpolynomial_fold
*fold_i
;
771 qp
= isl_qpolynomial_from_ginac(isl_dim_copy(dim
), *j
, params
);
772 fold_i
= isl_qpolynomial_fold_alloc(type
, qp
);
773 fold
= isl_qpolynomial_fold_fold(fold
, fold_i
);
779 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_from_ginac(
780 __isl_take isl_dim
*dim
, bernstein::piecewise_lst
*pl
,
781 const GiNaC::exvector
¶ms
)
784 isl_pw_qpolynomial_fold
*pwf
;
786 pwf
= isl_pw_qpolynomial_fold_zero(isl_dim_copy(dim
));
788 type
= pl
->sign
> 0 ? isl_fold_max
789 : pl
->sign
< 0 ? isl_fold_min
: isl_fold_list
;
791 for (int i
= 0; i
< pl
->list
.size(); ++i
) {
792 isl_pw_qpolynomial_fold
*pwf_i
;
793 isl_qpolynomial_fold
*fold
;
796 set
= isl_set_new_from_polylib(pl
->list
[i
].first
,
798 fold
= isl_qpolynomial_fold_from_ginac(isl_dim_copy(dim
),
799 type
, pl
->list
[i
].second
, params
);
800 pwf_i
= isl_pw_qpolynomial_fold_alloc(set
, fold
);
801 pwf
= isl_pw_qpolynomial_fold_add_disjoint(pwf
, pwf_i
);
819 static int guarded_qp_bernstein_coefficients(__isl_take isl_set
*set
,
820 __isl_take isl_qpolynomial
*qp
, void *user
)
822 struct isl_bound
*bound
= (struct isl_bound
*)user
;
825 struct barvinok_options
*options
;
828 options
= barvinok_options_new_with_defaults();
833 nvar
= isl_set_dim(set
, isl_dim_set
);
835 e
= isl_qpolynomial_to_evalue(qp
);
839 set
= isl_set_make_disjoint(set
);
840 D
= isl_set_to_polylib(set
);
842 bound
->vars
= constructVariableVector(nvar
, "v");
843 bound
->allvars
= bound
->vars
;
844 bound
->allvars
.insert(bound
->allvars
.end(),
845 bound
->params
.begin(), bound
->params
.end());
847 bound
->pl
= bernstein_coefficients_relation(bound
->pl
, D
, e
, bound
->U
,
848 bound
->allvars
, bound
->vars
, bound
->params
, options
);
853 isl_qpolynomial_free(qp
);
854 barvinok_options_free(options
);
859 isl_qpolynomial_free(qp
);
860 barvinok_options_free(options
);
864 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_bound_bernstein(
865 __isl_take isl_pw_qpolynomial
*pwqp
, enum isl_fold type
)
870 struct isl_bound bound
;
871 struct isl_pw_qpolynomial_fold
*pwf
;
876 dim
= isl_pw_qpolynomial_get_dim(pwqp
);
877 nvar
= isl_dim_size(dim
, isl_dim_set
);
879 if (isl_pw_qpolynomial_is_zero(pwqp
)) {
880 isl_pw_qpolynomial_free(pwqp
);
881 dim
= isl_dim_drop(dim
, isl_dim_set
, 0, nvar
);
882 return isl_pw_qpolynomial_fold_zero(dim
);
886 return isl_pw_qpolynomial_fold_from_pw_qpolynomial(type
, pwqp
);
889 nparam
= isl_dim_size(dim
, isl_dim_param
);
891 bound
.U
= Universe_Polyhedron(nparam
);
892 bound
.params
= constructVariableVector(nparam
, "p");
894 if (isl_pw_qpolynomial_foreach_lifted_piece(pwqp
,
895 guarded_qp_bernstein_coefficients
, &bound
))
898 if (type
== isl_fold_max
)
899 bound
.pl
->maximize();
901 bound
.pl
->minimize();
903 dim
= isl_dim_drop(dim
, isl_dim_set
, 0, nvar
);
905 if (type
== isl_fold_max
)
909 pwf
= isl_pw_qpolynomial_fold_from_ginac(dim
, bound
.pl
, bound
.params
);
911 Polyhedron_Free(bound
.U
);
914 isl_pw_qpolynomial_free(pwqp
);
918 isl_pw_qpolynomial_free(pwqp
);