2 #include <bernstein/bernstein.h>
3 #include <bernstein/piecewise_lst.h>
4 #include <barvinok/barvinok.h>
5 #include <barvinok/util.h>
6 #include <barvinok/bernstein.h>
7 #include <barvinok/options.h>
10 using namespace bernstein
;
19 ex
evalue2ex(evalue
*e
, const exvector
& vars
)
21 if (value_notzero_p(e
->d
))
22 return value2numeric(e
->x
.n
)/value2numeric(e
->d
);
23 if (e
->x
.p
->type
!= polynomial
)
26 for (int i
= e
->x
.p
->size
-1; i
>= 0; --i
) {
27 poly
*= vars
[e
->x
.p
->pos
-1];
28 ex t
= evalue2ex(&e
->x
.p
->arr
[i
], vars
);
29 if (is_exactly_a
<fail
>(t
))
36 static int type_offset(enode
*p
)
38 return p
->type
== fractional
? 1 :
39 p
->type
== flooring
? 1 : 0;
42 typedef pair
<bool, const evalue
*> typed_evalue
;
44 static ex
evalue2ex_add_var(evalue
*e
, exvector
& extravar
,
45 vector
<typed_evalue
>& expr
, bool is_fract
)
49 for (int i
= 0; i
< expr
.size(); ++i
) {
50 if (is_fract
== expr
[i
].first
&& eequal(e
, expr
[i
].second
)) {
51 base_var
= extravar
[i
];
59 snprintf(name
, sizeof(name
), "f%c%d", is_fract
? 'r' : 'l', expr
.size());
60 extravar
.push_back(base_var
= symbol(name
));
61 expr
.push_back(typed_evalue(is_fract
, e
));
66 static ex
evalue2ex_r(const evalue
*e
, const exvector
& vars
,
67 exvector
& extravar
, vector
<typed_evalue
>& expr
)
69 if (value_notzero_p(e
->d
))
70 return value2numeric(e
->x
.n
)/value2numeric(e
->d
);
74 switch (e
->x
.p
->type
) {
76 base_var
= vars
[e
->x
.p
->pos
-1];
79 base_var
= evalue2ex_add_var(&e
->x
.p
->arr
[0], extravar
, expr
, false);
82 base_var
= evalue2ex_add_var(&e
->x
.p
->arr
[0], extravar
, expr
, true);
88 int offset
= type_offset(e
->x
.p
);
89 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
91 ex t
= evalue2ex_r(&e
->x
.p
->arr
[i
], vars
, extravar
, expr
);
92 if (is_exactly_a
<fail
>(t
))
99 /* For each t = floor(e/d), set up two constraints
102 * -e + d t + d-1 >= 0
104 * e is assumed to be an affine expression.
106 * For each t = fract(e/d), set up two constraints
111 static Matrix
*setup_constraints(const vector
<typed_evalue
> expr
, int nvar
)
113 int extra
= expr
.size();
116 Matrix
*M
= Matrix_Alloc(2*extra
, 1+extra
+nvar
+1);
117 for (int i
= 0; i
< extra
; ++i
) {
118 Value
*d
= &M
->p
[2*i
][1+i
];
120 evalue_denom(expr
[i
].second
, d
);
122 value_set_si(M
->p
[2*i
][0], 1);
123 value_decrement(M
->p
[2*i
][1+extra
+nvar
], *d
);
124 value_oppose(*d
, *d
);
125 value_set_si(M
->p
[2*i
+1][0], 1);
126 value_set_si(M
->p
[2*i
+1][1+i
], 1);
129 for (e
= expr
[i
].second
; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[0]) {
130 assert(e
->x
.p
->type
== polynomial
);
131 assert(e
->x
.p
->size
== 2);
132 evalue
*c
= &e
->x
.p
->arr
[1];
133 value_multiply(M
->p
[2*i
][1+extra
+e
->x
.p
->pos
-1], *d
, c
->x
.n
);
134 value_division(M
->p
[2*i
][1+extra
+e
->x
.p
->pos
-1],
135 M
->p
[2*i
][1+extra
+e
->x
.p
->pos
-1], c
->d
);
137 value_multiply(M
->p
[2*i
][1+extra
+nvar
], *d
, e
->x
.n
);
138 value_division(M
->p
[2*i
][1+extra
+nvar
], M
->p
[2*i
][1+extra
+nvar
], e
->d
);
139 value_oppose(*d
, *d
);
140 value_set_si(M
->p
[2*i
][0], -1);
141 Vector_Scale(M
->p
[2*i
], M
->p
[2*i
+1], M
->p
[2*i
][0], 1+extra
+nvar
+1);
142 value_set_si(M
->p
[2*i
][0], 1);
143 value_subtract(M
->p
[2*i
+1][1+extra
+nvar
], M
->p
[2*i
+1][1+extra
+nvar
], *d
);
144 value_decrement(M
->p
[2*i
+1][1+extra
+nvar
], M
->p
[2*i
+1][1+extra
+nvar
]);
150 ex
evalue2ex(const evalue
*e
, const exvector
& vars
, exvector
& floorvar
, Matrix
**C
)
152 vector
<typed_evalue
> expr
;
153 ex poly
= evalue2ex_r(e
, vars
, floorvar
, expr
);
155 Matrix
*M
= setup_constraints(expr
, vars
.size());
160 /* if the evalue is a relation, we use the relation to cut off the
161 * the edges of the domain
163 static void evalue_extract_poly(evalue
*e
, int i
, Polyhedron
**D
, evalue
**poly
,
166 *D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
167 *poly
= e
= &e
->x
.p
->arr
[2*i
+1];
168 if (value_notzero_p(e
->d
))
170 if (e
->x
.p
->type
!= relation
)
172 if (e
->x
.p
->size
> 2)
174 evalue
*fr
= &e
->x
.p
->arr
[0];
175 assert(value_zero_p(fr
->d
));
176 assert(fr
->x
.p
->type
== fractional
);
177 assert(fr
->x
.p
->size
== 3);
178 Matrix
*T
= Matrix_Alloc(2, (*D
)->Dimension
+1);
179 value_set_si(T
->p
[1][(*D
)->Dimension
], 1);
181 /* convert argument of fractional to polylib */
182 /* the argument is assumed to be linear */
183 evalue
*p
= &fr
->x
.p
->arr
[0];
184 evalue_denom(p
, &T
->p
[1][(*D
)->Dimension
]);
185 for (;value_zero_p(p
->d
); p
= &p
->x
.p
->arr
[0]) {
186 assert(p
->x
.p
->type
== polynomial
);
187 assert(p
->x
.p
->size
== 2);
188 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
189 int pos
= p
->x
.p
->pos
- 1;
190 value_assign(T
->p
[0][pos
], p
->x
.p
->arr
[1].x
.n
);
191 value_multiply(T
->p
[0][pos
], T
->p
[0][pos
], T
->p
[1][(*D
)->Dimension
]);
192 value_division(T
->p
[0][pos
], T
->p
[0][pos
], p
->x
.p
->arr
[1].d
);
194 int pos
= (*D
)->Dimension
;
195 value_assign(T
->p
[0][pos
], p
->x
.n
);
196 value_multiply(T
->p
[0][pos
], T
->p
[0][pos
], T
->p
[1][(*D
)->Dimension
]);
197 value_division(T
->p
[0][pos
], T
->p
[0][pos
], p
->d
);
199 Polyhedron
*E
= NULL
;
200 for (Polyhedron
*P
= *D
; P
; P
= P
->next
) {
201 Polyhedron
*I
= Polyhedron_Image(P
, T
, MaxRays
);
202 I
= DomainConstraintSimplify(I
, MaxRays
);
203 Polyhedron
*R
= Polyhedron_Preimage(I
, T
, MaxRays
);
205 Polyhedron
*next
= P
->next
;
207 Polyhedron
*S
= DomainIntersection(P
, R
, MaxRays
);
213 E
= DomainConcat(S
, E
);
218 *poly
= &e
->x
.p
->arr
[1];
221 piecewise_lst
*evalue_bernstein_coefficients(piecewise_lst
*pl_all
, evalue
*e
,
222 Polyhedron
*ctx
, const exvector
& params
)
225 barvinok_options
*options
= barvinok_options_new_with_defaults();
226 pl
= evalue_bernstein_coefficients(pl_all
, e
, ctx
, params
, options
);
227 barvinok_options_free(options
);
231 piecewise_lst
*evalue_bernstein_coefficients(piecewise_lst
*pl_all
, evalue
*e
,
232 Polyhedron
*ctx
, const exvector
& params
,
233 barvinok_options
*options
)
235 unsigned nparam
= ctx
->Dimension
;
236 if (EVALUE_IS_ZERO(*e
))
238 assert(value_zero_p(e
->d
));
239 assert(e
->x
.p
->type
== partition
);
240 assert(e
->x
.p
->size
>= 2);
241 unsigned nvars
= EVALUE_DOMAIN(e
->x
.p
->arr
[0])->Dimension
- nparam
;
242 unsigned PP_MaxRays
= options
->MaxRays
;
243 if (PP_MaxRays
& POL_NO_DUAL
)
246 exvector vars
= constructVariableVector(nvars
, "v");
247 exvector allvars
= vars
;
248 allvars
.insert(allvars
.end(), params
.begin(), params
.end());
250 for (int i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
251 Param_Polyhedron
*PP
;
257 evalue_extract_poly(e
, i
, &E
, &EP
, options
->MaxRays
);
258 ex poly
= evalue2ex(EP
, allvars
, floorvar
, &M
);
259 floorvar
.insert(floorvar
.end(), vars
.begin(), vars
.end());
261 Polyhedron
*AE
= align_context(E
, M
->NbColumns
-2, options
->MaxRays
);
262 if (E
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
264 E
= DomainAddConstraints(AE
, M
, options
->MaxRays
);
268 if (is_exactly_a
<fail
>(poly
)) {
269 if (E
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
274 for (Polyhedron
*P
= E
; P
; P
= P
->next
) {
275 Polyhedron
*next
= P
->next
;
276 piecewise_lst
*pl
= new piecewise_lst(params
);
279 PP
= Polyhedron2Param_Domain(P
, ctx
, PP_MaxRays
);
280 for (Param_Domain
*Q
= PP
->D
; Q
; Q
= Q
->next
) {
281 matrix VM
= domainVertices(PP
, Q
, params
);
282 lst coeffs
= bernsteinExpansion(VM
, poly
, floorvar
, params
);
283 pl
->list
.push_back(guarded_lst(Polyhedron_Copy(Q
->Domain
), coeffs
));
285 Param_Polyhedron_Free(PP
);
289 pl_all
->combine(*pl
);
294 if (E
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))