laurent.cc: laurent_summator: member initializer list: put base classes first
[barvinok.git] / bound.c
blobd335efdfb730fdbd6e8900c3b12689ca9639e1da
1 #include <assert.h>
2 #include <isl/stream.h>
3 #include <barvinok/options.h>
4 #include <barvinok/util.h>
5 #include <barvinok/barvinok.h>
6 #include "verify.h"
8 struct options {
9 struct verify_options *verify;
10 long split;
11 int lower;
12 long iterate;
15 ISL_ARGS_START(struct options, options_args)
16 ISL_ARG_CHILD(struct options, verify, NULL,
17 &verify_options_args, "verification")
18 ISL_ARG_LONG(struct options, split, 0, "split", 0, NULL)
19 ISL_ARG_OPT_LONG(struct options, iterate, 0, "iterate", 0, -1,
20 "exact result by iterating over domain (of specified maximal size)")
21 ISL_ARG_BOOL(struct options, lower, 0, "lower", 0,
22 "compute lower bound instead of upper bound")
23 ISL_ARGS_END
25 ISL_ARG_DEF(options, struct options, options_args)
27 struct verify_point_bound {
28 struct verify_point_data vpd;
29 isl_pw_qpolynomial *pwqp;
30 isl_pw_qpolynomial_fold *pwf;
31 enum isl_fold type;
34 static isl_stat verify_point(__isl_take isl_point *pnt, void *user)
36 int i;
37 unsigned nparam;
38 struct verify_point_bound *vpb = (struct verify_point_bound *) user;
39 isl_val *v, *b, *q, *t;
40 isl_pw_qpolynomial *pwqp;
41 const char *minmax;
42 int sign;
43 isl_bool ok;
44 FILE *out = vpb->vpd.options->print_all ? stdout : stderr;
46 vpb->vpd.n--;
48 if (vpb->type == isl_fold_max) {
49 minmax = "max";
50 sign = 1;
51 } else {
52 minmax = "min";
53 sign = -1;
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 t = isl_point_get_coordinate_val(pnt, isl_dim_param, i);
61 pwqp = isl_pw_qpolynomial_fix_val(pwqp, isl_dim_param, i, t);
64 b = isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(vpb->pwf),
65 isl_point_copy(pnt));
67 if (sign > 0)
68 v = isl_pw_qpolynomial_max(pwqp);
69 else
70 v = isl_pw_qpolynomial_min(pwqp);
72 if (sign > 0)
73 v = isl_val_floor(v);
74 else
75 v = isl_val_ceil(v);
77 q = isl_val_copy(b);
78 if (sign > 0)
79 b = isl_val_floor(b);
80 else
81 b = isl_val_ceil(b);
83 if (sign > 0)
84 ok = isl_val_ge(b, v);
85 else
86 ok = isl_val_le(b, v);
88 if (vpb->vpd.options->print_all || !ok) {
89 isl_ctx *ctx = isl_point_get_ctx(pnt);
90 isl_printer *p;
91 p = isl_printer_to_file(ctx, out);
92 p = isl_printer_print_str(p, minmax);
93 p = isl_printer_print_str(p, "(");
94 for (i = 0; i < nparam; ++i) {
95 if (i)
96 p = isl_printer_print_str(p, ", ");
97 t = isl_point_get_coordinate_val(pnt, isl_dim_param, i);
98 p = isl_printer_print_val(p, t);
99 isl_val_free(t);
101 p = isl_printer_print_str(p, ") = ");
102 p = isl_printer_print_val(p, q);
103 if (!isl_val_is_int(q)) {
104 p = isl_printer_print_str(p, " (");
105 p = isl_printer_print_val(p, b);
106 p = isl_printer_print_str(p, ")");
108 p = isl_printer_print_str(p, ", ");
109 p = isl_printer_print_str(p, minmax);
110 p = isl_printer_print_str(p, "(EP) = ");
111 p = isl_printer_print_val(p, v);
112 if (ok)
113 p = isl_printer_print_str(p, ". OK");
114 else
115 p = isl_printer_print_str(p, ". NOT OK");
116 p = isl_printer_end_line(p);
117 isl_printer_free(p);
118 } else if ((vpb->vpd.n % vpb->vpd.s) == 0) {
119 printf("o");
120 fflush(stdout);
123 isl_point_free(pnt);
125 isl_val_free(b);
126 isl_val_free(q);
127 isl_val_free(v);
129 if (ok < 0 || !ok)
130 vpb->vpd.error = 1;
132 if (vpb->vpd.options->continue_on_error)
133 ok = isl_bool_true;
135 if (vpb->vpd.n < 1)
136 return isl_stat_error;
137 if (ok != isl_bool_true)
138 return isl_stat_error;
139 return isl_stat_ok;
142 static int verify(__isl_keep isl_pw_qpolynomial_fold *pwf,
143 __isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type,
144 struct verify_options *options)
146 struct verify_point_bound vpb = { { options } };
147 isl_set *context;
148 int r;
150 vpb.pwf = pwf;
151 vpb.type = type;
152 vpb.pwqp = pwqp;
153 context = isl_pw_qpolynomial_fold_domain(
154 isl_pw_qpolynomial_fold_copy(vpb.pwf));
155 context = verify_context_set_bounds(context, options);
157 r = verify_point_data_init(&vpb.vpd, context);
159 if (r == 0)
160 isl_set_foreach_point(context, verify_point, &vpb);
161 if (vpb.vpd.error)
162 r = -1;
164 isl_set_free(context);
165 isl_pw_qpolynomial_free(pwqp);
167 verify_point_data_fini(&vpb.vpd);
169 return r;
172 static __isl_give isl_pw_qpolynomial_fold *iterate(
173 __isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type)
175 isl_space *dim = isl_pw_qpolynomial_get_space(pwqp);
176 isl_set *set;
177 isl_val *v;
178 isl_qpolynomial *qp;
179 isl_qpolynomial_fold *fold;
180 unsigned nvar;
182 assert(isl_space_dim(dim, isl_dim_param) == 0);
183 nvar = isl_space_dim(dim, isl_dim_set);
185 if (type == isl_fold_min)
186 v = isl_pw_qpolynomial_min(pwqp);
187 else
188 v = isl_pw_qpolynomial_max(pwqp);
190 dim = isl_space_drop_dims(dim, isl_dim_set, 0, nvar);
191 qp = isl_qpolynomial_val_on_domain(isl_space_copy(dim), v);
192 fold = isl_qpolynomial_fold_alloc(type, qp);
193 set = isl_set_universe(dim);
195 return isl_pw_qpolynomial_fold_alloc(type, set, fold);
198 struct bv_split_data {
199 int size;
200 __isl_give isl_pw_qpolynomial *pwqp_less;
201 __isl_give isl_pw_qpolynomial *pwqp_more;
204 static isl_stat split_on_size(__isl_take isl_set *set,
205 __isl_take isl_qpolynomial *qp, void *user)
207 struct bv_split_data *data = (struct bv_split_data *)user;
208 int bounded;
209 isl_set *set_np;
210 isl_pw_qpolynomial *pwqp;
211 int nparam;
213 nparam = isl_set_dim(set, isl_dim_param);
214 set_np = isl_set_move_dims(isl_set_copy(set), isl_dim_set, 0,
215 isl_dim_param, 0, nparam);
216 bounded = isl_set_is_bounded(set_np);
217 assert(bounded >= 0);
218 if (bounded) {
219 isl_pw_qpolynomial *pwqp;
220 isl_val *m;
222 pwqp = isl_set_card(set_np);
223 m = isl_pw_qpolynomial_max(pwqp);
224 bounded = isl_val_cmp_si(m, data->size) <= 0;
225 isl_val_free(m);
226 } else
227 isl_set_free(set_np);
229 pwqp = isl_pw_qpolynomial_alloc(set, qp);
230 if (bounded)
231 data->pwqp_less = isl_pw_qpolynomial_add_disjoint(
232 data->pwqp_less, pwqp);
233 else
234 data->pwqp_more = isl_pw_qpolynomial_add_disjoint(
235 data->pwqp_more, pwqp);
237 return isl_stat_ok;
241 * Split (partition) pwpq into a partition with (sub)domains containing
242 * size integer points or less and a partition with (sub)domains
243 * containing more integer points.
245 static int split_on_domain_size(__isl_take isl_pw_qpolynomial *pwqp,
246 __isl_give isl_pw_qpolynomial **pwqp_less,
247 __isl_give isl_pw_qpolynomial **pwqp_more,
248 int size)
250 isl_space *dim;
251 struct bv_split_data data = { size };
252 int r;
254 dim = isl_pw_qpolynomial_get_space(pwqp);
255 data.pwqp_less = isl_pw_qpolynomial_zero(isl_space_copy(dim));
256 data.pwqp_more = isl_pw_qpolynomial_zero(dim);
257 r = isl_pw_qpolynomial_foreach_piece(pwqp, &split_on_size, &data);
258 *pwqp_less = data.pwqp_less;
259 *pwqp_more = data.pwqp_more;
260 isl_pw_qpolynomial_free(pwqp);
262 return r;
265 static __isl_give isl_pw_qpolynomial_fold *optimize(
266 __isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type,
267 struct options *options)
269 isl_pw_qpolynomial_fold *pwf;
271 if (options->iterate > 0) {
272 isl_pw_qpolynomial *pwqp_less, *pwqp_more;
273 isl_pw_qpolynomial_fold *pwf_less, *pwf_more;
274 split_on_domain_size(pwqp, &pwqp_less, &pwqp_more, options->iterate);
275 pwf_less = iterate(pwqp_less, type);
276 pwf_more = isl_pw_qpolynomial_bound(pwqp_more, type, NULL);
277 pwf = isl_pw_qpolynomial_fold_fold(pwf_less, pwf_more);
278 } else if (options->iterate)
279 pwf = iterate(pwqp, type);
280 else
281 pwf = isl_pw_qpolynomial_bound(pwqp, type, NULL);
282 return pwf;
285 static int optimize_and_print(__isl_take isl_pw_qpolynomial *pwqp,
286 struct options *options)
288 int print_solution = 1;
289 int result = 0;
290 isl_pw_qpolynomial_fold *pwf;
291 enum isl_fold type = options->lower ? isl_fold_min : isl_fold_max;
293 if (options->verify->verify) {
294 isl_space *dim = isl_pw_qpolynomial_get_space(pwqp);
295 unsigned total = isl_space_dim(dim, isl_dim_all);
296 isl_space_free(dim);
297 verify_options_set_range(options->verify, total);
298 if (!options->verify->barvinok->verbose)
299 print_solution = 0;
302 pwf = optimize(isl_pw_qpolynomial_copy(pwqp), type, options);
303 assert(pwf);
304 if (print_solution) {
305 isl_ctx *ctx = isl_pw_qpolynomial_get_ctx(pwqp);
306 isl_printer *p = isl_printer_to_file(ctx, stdout);
307 p = isl_printer_print_pw_qpolynomial_fold(p, pwf);
308 p = isl_printer_end_line(p);
309 isl_printer_free(p);
311 if (options->verify->verify) {
312 enum isl_fold type = options->lower ? isl_fold_min : isl_fold_max;
313 result = verify(pwf, pwqp, type, options->verify);
314 } else
315 isl_pw_qpolynomial_free(pwqp);
316 isl_pw_qpolynomial_fold_free(pwf);
318 return result;
321 int main(int argc, char **argv)
323 struct options *options = options_new_with_defaults();
324 isl_ctx *ctx;
325 isl_pw_qpolynomial *pwqp;
326 struct isl_stream *s;
327 int result = 0;
329 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
330 ctx = isl_ctx_alloc_with_options(&options_args, options);
332 s = isl_stream_new_file(ctx, stdin);
333 pwqp = isl_stream_read_pw_qpolynomial(s);
335 if (options->split)
336 pwqp = isl_pw_qpolynomial_split_periods(pwqp, options->split);
338 result = optimize_and_print(pwqp, options);
340 isl_stream_free(s);
341 isl_ctx_free(ctx);
342 return result;