3 #include <barvinok/util.h>
5 #include "evalue_util.h"
11 static void print_term(ostream
& os
, Value v
, int pos
, int dim
,
12 char **names
, int *first
)
14 if (value_zero_p(v
)) {
15 if (first
&& *first
&& pos
>= dim
)
21 if (!*first
&& value_pos_p(v
))
26 if (value_mone_p(v
)) {
28 } else if (!value_one_p(v
))
29 os
<< VALUE_TO_INT(v
);
32 os
<< VALUE_TO_INT(v
);
35 void EDomain_floor::print(ostream
& os
, char **p
) const
40 for (int i
= 0; i
< v
->Size
-2; ++i
)
41 print_term(os
, v
->p
[1+i
], i
, v
->Size
-2, p
, &first
);
44 print_term(os
, v
->p
[0], v
->Size
-2, v
->Size
-2, p
, NULL
);
48 void EDomain::print_constraints(ostream
& os
, char **p
,
49 barvinok_options
*options
) const
54 Matrix
*M
= Matrix_Alloc(2*floors
.size(), 1+D
->Dimension
+1);
55 value_set_si(tmp
, -1);
56 for (int i
= 0; i
< floors
.size(); ++i
) {
57 value_set_si(M
->p
[2*i
][0], 1);
58 Vector_Copy(floors
[i
]->v
->p
+1, M
->p
[2*i
]+1, dimension());
59 value_assign(M
->p
[2*i
][1+D
->Dimension
], floors
[i
]->v
->p
[1+dimension()]);
60 value_oppose(M
->p
[2*i
][1+dimension()+i
], floors
[i
]->v
->p
[0]);
62 Vector_Scale(M
->p
[2*i
]+1, M
->p
[2*i
+1]+1, tmp
, D
->Dimension
+1);
63 value_addto(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
],
64 M
->p
[2*i
+1][1+dimension()+i
]);
65 value_decrement(M
->p
[2*i
+1][1+D
->Dimension
], M
->p
[2*i
+1][1+D
->Dimension
]);
66 value_set_si(M
->p
[2*i
+1][0], 1);
68 Polyhedron
*E
= Constraints2Polyhedron(M
, options
->MaxRays
);
70 Polyhedron
*SD
= DomainSimplify(D
, E
, options
->MaxRays
);
74 unsigned dim
= dimension();
75 if (dim
< SD
->Dimension
) {
76 names
= new char * [SD
->Dimension
];
78 for (i
= 0; i
< dim
; ++i
)
80 for ( ; i
< SD
->Dimension
; ++i
) {
81 std::ostringstream strm
;
82 floors
[i
-dim
]->print(strm
, p
);
83 names
[i
] = strdup(strm
.str().c_str());
87 for (int i
= 0; i
< SD
->NbConstraints
; ++i
) {
89 int v
= First_Non_Zero(SD
->Constraint
[i
]+1, SD
->Dimension
);
94 if (value_pos_p(SD
->Constraint
[i
][v
+1])) {
95 print_term(os
, SD
->Constraint
[i
][v
+1], v
, SD
->Dimension
,
97 if (value_zero_p(SD
->Constraint
[i
][0]))
101 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
) {
102 value_oppose(tmp
, SD
->Constraint
[i
][1+j
]);
103 print_term(os
, tmp
, j
, SD
->Dimension
,
107 value_oppose(tmp
, SD
->Constraint
[i
][1+v
]);
108 print_term(os
, tmp
, v
, SD
->Dimension
,
110 if (value_zero_p(SD
->Constraint
[i
][0]))
114 for (int j
= v
+1; j
<= SD
->Dimension
; ++j
)
115 print_term(os
, SD
->Constraint
[i
][1+j
], j
, SD
->Dimension
,
122 if (dim
< D
->Dimension
) {
123 for (int i
= dim
; i
< D
->Dimension
; ++i
)
129 void EDomain::print(FILE *out
, char **p
)
131 fdostream
os(dup(fileno(out
)));
132 for (int i
= 0; i
< floors
.size(); ++i
) {
133 os
<< "floor " << i
<< ": [";
134 evalue_print(os
, floors
[i
]->e
, p
);
137 Polyhedron_Print(out
, P_VALUE_FMT
, D
);
140 static int type_offset(enode
*p
)
142 return p
->type
== fractional
? 1 :
143 p
->type
== flooring
? 1 : 0;
146 static void add_coeff(Value
*cons
, int len
, evalue
*coeff
, int pos
)
150 assert(value_notzero_p(coeff
->d
));
154 value_lcm(cons
[0], coeff
->d
, &tmp
);
155 value_division(tmp
, tmp
, cons
[0]);
156 Vector_Scale(cons
, cons
, tmp
, len
);
157 value_division(tmp
, cons
[0], coeff
->d
);
158 value_addmul(cons
[pos
], tmp
, coeff
->x
.n
);
163 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
);
165 static void add_fract(evalue
*e
, Value
*cons
, int len
, int pos
)
169 evalue_set_si(&mone
, -1, 1);
171 /* contribution of alpha * fract(X) is
174 assert(e
->x
.p
->size
== 3);
176 value_init(argument
.d
);
177 evalue_copy(&argument
, &e
->x
.p
->arr
[0]);
178 emul(&e
->x
.p
->arr
[2], &argument
);
179 evalue2constraint_r(NULL
, &argument
, cons
, len
);
180 free_evalue_refs(&argument
);
182 /* - alpha * floor(X) */
183 emul(&mone
, &e
->x
.p
->arr
[2]);
184 add_coeff(cons
, len
, &e
->x
.p
->arr
[2], pos
);
185 emul(&mone
, &e
->x
.p
->arr
[2]);
187 free_evalue_refs(&mone
);
190 static int evalue2constraint_r(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
193 if (value_zero_p(E
->d
) && E
->x
.p
->type
== fractional
) {
195 assert(E
->x
.p
->size
== 3);
196 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[1], cons
, len
);
197 assert(value_notzero_p(E
->x
.p
->arr
[2].d
));
198 if (D
&& (i
= D
->find_floor(&E
->x
.p
->arr
[0])) >= 0) {
199 add_fract(E
, cons
, len
, 1+D
->D
->Dimension
-D
->floors
.size()+i
);
201 if (value_pos_p(E
->x
.p
->arr
[2].x
.n
)) {
204 value_init(coeff
.x
.n
);
205 value_set_si(coeff
.d
, 1);
206 evalue_denom(&E
->x
.p
->arr
[0], &coeff
.d
);
207 value_decrement(coeff
.x
.n
, coeff
.d
);
208 emul(&E
->x
.p
->arr
[2], &coeff
);
209 add_coeff(cons
, len
, &coeff
, len
-1);
210 free_evalue_refs(&coeff
);
214 } else if (value_zero_p(E
->d
)) {
215 assert(E
->x
.p
->type
== polynomial
);
216 assert(E
->x
.p
->size
== 2);
217 r
= evalue2constraint_r(D
, &E
->x
.p
->arr
[0], cons
, len
) || r
;
218 add_coeff(cons
, len
, &E
->x
.p
->arr
[1], E
->x
.p
->pos
);
220 add_coeff(cons
, len
, E
, len
-1);
225 EDomain_floor::EDomain_floor(const evalue
*f
, int dim
)
230 v
= Vector_Alloc(1+dim
+1);
231 value_set_si(v
->p
[0], 1);
232 evalue2constraint_r(NULL
, e
, v
->p
, v
->Size
);
237 void EDomain_floor::eval(Value
*values
, Value
*res
) const
239 Inner_Product(v
->p
+1, values
, v
->Size
-2, res
);
240 value_addto(*res
, *res
, v
->p
[v
->Size
-1]);
241 value_pdivision(*res
, *res
, v
->p
[0]);
244 int evalue2constraint(EDomain
*D
, evalue
*E
, Value
*cons
, int len
)
246 Vector_Set(cons
, 0, len
);
247 value_set_si(cons
[0], 1);
248 return evalue2constraint_r(D
, E
, cons
, len
);
251 bool EDomain::contains(Value
*point
, int len
) const
253 assert(len
<= D
->Dimension
);
254 if (len
== D
->Dimension
)
255 return in_domain(D
, point
);
257 Vector
*all_val
= Vector_Alloc(D
->Dimension
);
258 Vector_Copy(point
, all_val
->p
, len
);
259 for (int i
= len
-dimension(); i
< floors
.size(); ++i
)
260 floors
[i
]->eval(all_val
->p
, &all_val
->p
[dimension()+i
]);
261 bool in
= in_domain(D
, all_val
->p
);
262 Vector_Free(all_val
);
266 Matrix
*EDomain::add_ge_constraint(evalue
*constraint
,
267 vector
<EDomain_floor
*>& new_floors
) const
271 evalue_set_si(&mone
, -1, 1);
273 for (evalue
*e
= constraint
; value_zero_p(e
->d
);
274 e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
276 if (e
->x
.p
->type
!= fractional
)
278 if (find_floor(&e
->x
.p
->arr
[0]) == -1)
282 int rows
= D
->NbConstraints
+2*fract
+1;
283 int cols
= 2+D
->Dimension
+fract
;
284 Matrix
*M
= Matrix_Alloc(rows
, cols
);
285 for (int i
= 0; i
< D
->NbConstraints
; ++i
) {
286 Vector_Copy(D
->Constraint
[i
], M
->p
[i
], 1+D
->Dimension
);
287 value_assign(M
->p
[i
][1+D
->Dimension
+fract
],
288 D
->Constraint
[i
][1+D
->Dimension
]);
290 value_set_si(M
->p
[rows
-1][0], 1);
293 for (e
= constraint
; value_zero_p(e
->d
); e
= &e
->x
.p
->arr
[type_offset(e
->x
.p
)]) {
294 if (e
->x
.p
->type
== fractional
) {
297 i
= find_floor(&e
->x
.p
->arr
[0]);
299 pos
= D
->Dimension
-floors
.size()+i
;
301 pos
= D
->Dimension
+fract
;
303 add_fract(e
, M
->p
[rows
-1], cols
, 1+pos
);
305 if (pos
< D
->Dimension
)
308 EDomain_floor
*new_floor
;
309 new_floor
= new EDomain_floor(&e
->x
.p
->arr
[0], dimension());
311 /* constraints for the new floor */
312 int row
= D
->NbConstraints
+2*fract
;
313 Vector_Copy(new_floor
->v
->p
+1, M
->p
[row
]+1, dimension());
314 value_assign(M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]);
315 value_oppose(M
->p
[row
][1+D
->Dimension
+fract
], new_floor
->v
->p
[0]);
316 value_set_si(M
->p
[row
][0], 1);
317 assert(value_eq(M
->p
[row
][cols
-1], new_floor
->v
->p
[1+dimension()]));
318 assert(Vector_Equal(new_floor
->v
->p
+1, M
->p
[row
]+1, dimension()));
320 Vector_Scale(M
->p
[row
]+1, M
->p
[row
+1]+1, mone
.x
.n
, cols
-1);
321 value_set_si(M
->p
[row
+1][0], 1);
322 value_addto(M
->p
[row
+1][cols
-1], M
->p
[row
+1][cols
-1],
323 M
->p
[row
+1][1+D
->Dimension
+fract
]);
324 value_decrement(M
->p
[row
+1][cols
-1], M
->p
[row
+1][cols
-1]);
326 new_floors
.push_back(new_floor
);
330 assert(e
->x
.p
->type
== polynomial
);
331 assert(e
->x
.p
->size
== 2);
332 add_coeff(M
->p
[rows
-1], cols
, &e
->x
.p
->arr
[1], e
->x
.p
->pos
);
335 add_coeff(M
->p
[rows
-1], cols
, e
, cols
-1);
336 value_set_si(M
->p
[rows
-1][0], 1);
337 free_evalue_refs(&mone
);
341 /* "align" matrix to have nrows by inserting
342 * the necessary number of rows and an equal number of columns at the end
343 * right before the constant row/column
345 static Matrix
*align_matrix_initial(Matrix
*M
, int nrows
)
348 int newrows
= nrows
- M
->NbRows
;
349 Matrix
*M2
= Matrix_Alloc(nrows
, newrows
+ M
->NbColumns
);
350 for (i
= 0; i
< M
->NbRows
-1; ++i
) {
351 Vector_Copy(M
->p
[i
], M2
->p
[i
], M
->NbColumns
-1);
352 value_assign(M2
->p
[i
][M2
->NbColumns
-1], M
->p
[i
][M
->NbColumns
-1]);
354 for (i
= 0; i
<= newrows
; ++i
)
355 value_assign(M2
->p
[M
->NbRows
-1+i
][M
->NbColumns
-1+i
],
356 M
->p
[M
->NbRows
-1][M
->NbColumns
-1]);
360 static Matrix
*InsertColumns(Matrix
*M
, int pos
, int n
)
365 R
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+n
);
366 for (i
= 0; i
< M
->NbRows
; ++i
) {
367 Vector_Copy(M
->p
[i
], R
->p
[i
], pos
);
368 Vector_Copy(M
->p
[i
]+pos
, R
->p
[i
]+pos
+n
, M
->NbColumns
-pos
);
373 void evalue_substitute(evalue
*e
, evalue
**subs
)
377 if (value_notzero_p(e
->d
))
381 for (int i
= 0; i
< p
->size
; ++i
)
382 evalue_substitute(&p
->arr
[i
], subs
);
384 if (p
->type
== polynomial
)
389 value_set_si(v
->d
, 0);
390 v
->x
.p
= new_enode(p
->type
, 3, -1);
391 value_clear(v
->x
.p
->arr
[0].d
);
392 v
->x
.p
->arr
[0] = p
->arr
[0];
393 evalue_set_si(&v
->x
.p
->arr
[1], 0, 1);
394 evalue_set_si(&v
->x
.p
->arr
[2], 1, 1);
397 int offset
= type_offset(p
);
399 for (int i
= p
->size
-1; i
>= offset
+1; i
--) {
401 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
402 free_evalue_refs(&(p
->arr
[i
]));
405 if (p
->type
!= polynomial
) {
415 void EDomain_floor::substitute(evalue
**subs
, Matrix
*T
)
417 /* This is a hack. The EDomain_floor elements are possibly shared
418 * by many EDomain structures and we want to perform the substitution
425 evalue_substitute(e
, subs
);
427 assert(T
->NbRows
== v
->Size
-1);
428 Vector
*tmp
= Vector_Alloc(1+T
->NbColumns
);
429 Vector_Matrix_Product(v
->p
+1, T
, tmp
->p
+1);
430 value_multiply(tmp
->p
[0], v
->p
[0], T
->p
[T
->NbRows
-1][T
->NbColumns
-1]);
435 /* T is a homogeneous matrix that maps the original variables to the new variables.
436 * this has constraints in the new variables and this method
437 * transforms this to constraints in the original variables.
439 void EDomain::substitute(evalue
**subs
, Matrix
*T
, Matrix
*Eq
, unsigned MaxRays
)
441 int nexist
= floors
.size();
442 Matrix
*M
= align_matrix_initial(T
, T
->NbRows
+nexist
);
443 Polyhedron
*new_D
= DomainPreimage(D
, M
, MaxRays
);
448 M
= nexist
? InsertColumns(Eq
, 1+dimension(), nexist
) : Eq
;
449 new_D
= DomainAddConstraints(D
, M
, MaxRays
);
454 for (int i
= 0; i
< floors
.size(); ++i
)
455 floors
[i
]->substitute(subs
, T
);