3 #include <barvinok/evalue.h>
4 #include <barvinok/options.h>
5 #include <barvinok/util.h>
6 #include <barvinok/barvinok.h>
7 #include "bound_options.h"
8 #include "evalue_convert.h"
9 #include "evalue_read.h"
16 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
18 struct verify_point_bound
{
19 struct verify_point_data vpd
;
20 isl_pw_qpolynomial
*pwqp
;
21 isl_pw_qpolynomial_fold
*pwf
;
25 static int verify_point(__isl_take isl_point
*pnt
, void *user
)
29 struct verify_point_bound
*vpb
= (struct verify_point_bound
*) user
;
30 isl_int v
, n
, d
, b
, t
;
31 isl_pw_qpolynomial
*pwqp
;
32 isl_qpolynomial
*bound
;
38 FILE *out
= vpb
->vpd
.options
->print_all
? stdout
: stderr
;
42 if (vpb
->type
== isl_fold_max
) {
56 pwqp
= isl_pw_qpolynomial_copy(vpb
->pwqp
);
58 nparam
= isl_pw_qpolynomial_dim(pwqp
, isl_dim_param
);
59 for (i
= 0; i
< nparam
; ++i
) {
60 isl_point_get_coordinate(pnt
, isl_dim_param
, i
, &v
);
61 pwqp
= isl_pw_qpolynomial_fix_dim(pwqp
, isl_dim_param
, i
, v
);
64 bound
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(vpb
->pwf
),
68 opt
= isl_pw_qpolynomial_max(pwqp
);
70 opt
= isl_pw_qpolynomial_min(pwqp
);
72 cst
= isl_qpolynomial_is_cst(opt
, &n
, &d
);
76 isl_int_fdiv_q(v
, n
, d
);
78 isl_int_cdiv_q(v
, n
, d
);
80 cst
= isl_qpolynomial_is_cst(bound
, &n
, &d
);
84 isl_int_fdiv_q(b
, n
, d
);
86 isl_int_cdiv_q(b
, n
, d
);
93 if (vpb
->vpd
.options
->print_all
|| !ok
) {
94 fprintf(out
, "%s(", minmax
);
95 for (i
= 0; i
< nparam
; ++i
) {
98 isl_point_get_coordinate(pnt
, isl_dim_param
, i
, &t
);
99 isl_int_print(out
, t
, 0);
101 fprintf(out
, ") = ");
102 isl_int_print(out
, n
, 0);
103 if (!isl_int_is_one(d
)) {
105 isl_int_print(out
, d
, 0);
107 isl_int_print(out
, b
, 0);
110 fprintf(out
, ", %s(EP) = ", minmax
);
111 isl_int_print(out
, v
, 0);
113 fprintf(out
, ". OK\n");
115 fprintf(out
, ". NOT OK\n");
116 } else if ((vpb
->vpd
.n
% vpb
->vpd
.s
) == 0) {
126 isl_qpolynomial_free(bound
);
127 isl_qpolynomial_free(opt
);
139 if (vpb
->vpd
.options
->continue_on_error
)
142 return (vpb
->vpd
.n
>= 1 && ok
) ? 0 : -1;
145 static int verify(__isl_keep isl_pw_qpolynomial_fold
*pwf
,
146 __isl_take isl_pw_qpolynomial
*pwqp
, enum isl_fold type
,
147 struct verify_options
*options
)
149 struct verify_point_bound vpb
= { { options
} };
154 ctx
= isl_pw_qpolynomial_fold_get_ctx(pwf
);
158 context
= isl_pw_qpolynomial_fold_domain(
159 isl_pw_qpolynomial_fold_copy(vpb
.pwf
));
160 context
= verify_context_set_bounds(context
, options
);
162 r
= verify_point_data_init(&vpb
.vpd
, context
);
165 isl_set_foreach_point(context
, verify_point
, &vpb
);
169 isl_set_free(context
);
170 isl_pw_qpolynomial_free(pwqp
);
172 verify_point_data_fini(&vpb
.vpd
);
177 static __isl_give isl_pw_qpolynomial_fold
*iterate(
178 __isl_take isl_pw_qpolynomial
*pwqp
, enum isl_fold type
)
180 isl_dim
*dim
= isl_pw_qpolynomial_get_dim(pwqp
);
183 isl_qpolynomial_fold
*fold
;
186 assert(isl_dim_size(dim
, isl_dim_param
) == 0);
187 nvar
= isl_dim_size(dim
, isl_dim_set
);
189 if (type
== isl_fold_min
)
190 qp
= isl_pw_qpolynomial_min(pwqp
);
192 qp
= isl_pw_qpolynomial_max(pwqp
);
194 qp
= isl_qpolynomial_drop_dims(qp
, isl_dim_set
, 0, nvar
);
195 fold
= isl_qpolynomial_fold_alloc(type
, qp
);
196 dim
= isl_dim_drop(dim
, isl_dim_set
, 0, nvar
);
197 set
= isl_set_universe(dim
);
199 return isl_pw_qpolynomial_fold_alloc(type
, set
, fold
);
202 struct bv_split_data
{
204 __isl_give isl_pw_qpolynomial
*pwqp_less
;
205 __isl_give isl_pw_qpolynomial
*pwqp_more
;
208 static int split_on_size(__isl_take isl_set
*set
,
209 __isl_take isl_qpolynomial
*qp
, void *user
)
211 struct bv_split_data
*data
= (struct bv_split_data
*)user
;
214 isl_pw_qpolynomial
*pwqp
;
217 nparam
= isl_set_dim(set
, isl_dim_param
);
218 set_np
= isl_set_move_dims(isl_set_copy(set
), isl_dim_set
, 0,
219 isl_dim_param
, 0, nparam
);
220 bounded
= isl_set_is_bounded(set_np
);
221 assert(bounded
>= 0);
223 isl_pw_qpolynomial
*pwqp
;
224 isl_qpolynomial
*cst
;
228 pwqp
= isl_set_card(set_np
);
229 cst
= isl_pw_qpolynomial_max(pwqp
);
231 is_cst
= isl_qpolynomial_is_cst(cst
, &m
, NULL
);
232 isl_qpolynomial_free(cst
);
234 bounded
= isl_int_cmp_si(m
, data
->size
) <= 0;
237 isl_set_free(set_np
);
239 pwqp
= isl_pw_qpolynomial_alloc(set
, qp
);
241 data
->pwqp_less
= isl_pw_qpolynomial_add_disjoint(
242 data
->pwqp_less
, pwqp
);
244 data
->pwqp_more
= isl_pw_qpolynomial_add_disjoint(
245 data
->pwqp_more
, pwqp
);
251 * Split (partition) pwpq into a partition with (sub)domains containing
252 * size integer points or less and a partition with (sub)domains
253 * containing more integer points.
255 static int split_on_domain_size(__isl_take isl_pw_qpolynomial
*pwqp
,
256 __isl_give isl_pw_qpolynomial
**pwqp_less
,
257 __isl_give isl_pw_qpolynomial
**pwqp_more
,
261 struct bv_split_data data
= { size
};
264 dim
= isl_pw_qpolynomial_get_dim(pwqp
);
265 data
.pwqp_less
= isl_pw_qpolynomial_zero(isl_dim_copy(dim
));
266 data
.pwqp_more
= isl_pw_qpolynomial_zero(dim
);
267 r
= isl_pw_qpolynomial_foreach_piece(pwqp
, &split_on_size
, &data
);
268 *pwqp_less
= data
.pwqp_less
;
269 *pwqp_more
= data
.pwqp_more
;
270 isl_pw_qpolynomial_free(pwqp
);
275 static __isl_give isl_pw_qpolynomial_fold
*optimize(
276 __isl_take isl_pw_qpolynomial
*pwqp
, enum isl_fold type
,
277 struct options
*options
)
279 isl_pw_qpolynomial_fold
*pwf
;
281 if (options
->iterate
> 0) {
282 isl_pw_qpolynomial
*pwqp_less
, *pwqp_more
;
283 isl_pw_qpolynomial_fold
*pwf_less
, *pwf_more
;
284 split_on_domain_size(pwqp
, &pwqp_less
, &pwqp_more
, options
->iterate
);
285 pwf_less
= iterate(pwqp_less
, type
);
286 pwf_more
= isl_pw_qpolynomial_bound(pwqp_more
, type
, NULL
);
287 pwf
= isl_pw_qpolynomial_fold_fold(pwf_less
, pwf_more
);
288 } else if (options
->iterate
)
289 pwf
= iterate(pwqp
, type
);
291 pwf
= isl_pw_qpolynomial_bound(pwqp
, type
, NULL
);
295 static int optimize(evalue
*EP
, const char **all_vars
,
296 unsigned nvar
, unsigned nparam
, struct options
*options
)
298 int print_solution
= 1;
300 isl_ctx
*ctx
= isl_ctx_alloc_with_options(options_arg
, options
);
302 isl_pw_qpolynomial_fold
*pwf
;
303 isl_pw_qpolynomial
*pwqp
;
304 enum isl_fold type
= options
->lower
? isl_fold_min
: isl_fold_max
;
306 dim
= isl_dim_set_alloc(ctx
, nparam
, 0);
307 for (int i
= 0; i
< nparam
; ++i
)
308 dim
= isl_dim_set_name(dim
, isl_dim_param
, i
, all_vars
[nvar
+ i
]);
310 if (options
->verify
->verify
) {
311 verify_options_set_range(options
->verify
, nvar
+nparam
);
312 if (!options
->verify
->barvinok
->verbose
)
316 dim
= isl_dim_insert(dim
, isl_dim_param
, 0, nvar
);
317 pwqp
= isl_pw_qpolynomial_from_evalue(dim
, EP
);
318 pwqp
= isl_pw_qpolynomial_move_dims(pwqp
, isl_dim_set
, 0, isl_dim_param
, 0, nvar
);
319 pwf
= optimize(isl_pw_qpolynomial_copy(pwqp
), type
, options
);
321 if (print_solution
) {
322 isl_printer
*p
= isl_printer_to_file(ctx
, stdout
);
323 p
= isl_printer_print_pw_qpolynomial_fold(p
, pwf
);
324 p
= isl_printer_end_line(p
);
327 if (options
->verify
->verify
) {
328 enum isl_fold type
= options
->lower
? isl_fold_min
: isl_fold_max
;
329 result
= verify(pwf
, pwqp
, type
, options
->verify
);
331 isl_pw_qpolynomial_free(pwqp
);
332 isl_pw_qpolynomial_fold_free(pwf
);
339 int main(int argc
, char **argv
)
342 const char **all_vars
= NULL
;
345 struct options
*options
= options_new_with_defaults();
348 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
350 EP
= evalue_read_from_file(stdin
, options
->var_list
, &all_vars
,
351 &nvar
, &nparam
, options
->verify
->barvinok
->MaxRays
);
355 evalue_split_periods(EP
, options
->split
, options
->verify
->barvinok
->MaxRays
);
357 evalue_convert(EP
, options
->convert
, options
->verify
->barvinok
->verbose
,
358 nvar
+nparam
, all_vars
);
360 if (EVALUE_IS_ZERO(*EP
))
361 print_evalue(stdout
, EP
, all_vars
);
363 result
= optimize(EP
, all_vars
, nvar
, nparam
, options
);
367 Free_ParamNames(all_vars
, nvar
+nparam
);