1 1.1 mrg #include <assert.h> 2 1.1 mrg #include <isl/stream.h> 3 1.1 mrg #include <isl_map_private.h> 4 1.1 mrg #include <isl/polynomial.h> 5 1.1 mrg #include <isl_scan.h> 6 1.1 mrg #include <isl/val.h> 7 1.1 mrg #include <isl/options.h> 8 1.1 mrg 9 1.1 mrg struct bound_options { 10 1.1 mrg struct isl_options *isl; 11 1.1 mrg unsigned verify; 12 1.1 mrg int print_all; 13 1.1 mrg int continue_on_error; 14 1.1 mrg }; 15 1.1 mrg 16 1.1 mrg ISL_ARGS_START(struct bound_options, bound_options_args) 17 1.1 mrg ISL_ARG_CHILD(struct bound_options, isl, "isl", &isl_options_args, 18 1.1 mrg "isl options") 19 1.1 mrg ISL_ARG_BOOL(struct bound_options, verify, 'T', "verify", 0, NULL) 20 1.1 mrg ISL_ARG_BOOL(struct bound_options, print_all, 'A', "print-all", 0, NULL) 21 1.1 mrg ISL_ARG_BOOL(struct bound_options, continue_on_error, '\0', "continue-on-error", 0, NULL) 22 1.1 mrg ISL_ARGS_END 23 1.1 mrg 24 1.1 mrg ISL_ARG_DEF(bound_options, struct bound_options, bound_options_args) 25 1.1 mrg 26 1.1 mrg static __isl_give isl_set *set_bounds(__isl_take isl_set *set) 27 1.1 mrg { 28 1.1 mrg isl_size nparam; 29 1.1 mrg int i, r; 30 1.1 mrg isl_point *pt, *pt2; 31 1.1 mrg isl_set *box; 32 1.1 mrg 33 1.1 mrg nparam = isl_set_dim(set, isl_dim_param); 34 1.1 mrg if (nparam < 0) 35 1.1 mrg return isl_set_free(set); 36 1.1 mrg r = nparam >= 8 ? 5 : nparam >= 5 ? 15 : 50; 37 1.1 mrg 38 1.1 mrg pt = isl_set_sample_point(isl_set_copy(set)); 39 1.1 mrg pt2 = isl_point_copy(pt); 40 1.1 mrg 41 1.1 mrg for (i = 0; i < nparam; ++i) { 42 1.1 mrg pt = isl_point_add_ui(pt, isl_dim_param, i, r); 43 1.1 mrg pt2 = isl_point_sub_ui(pt2, isl_dim_param, i, r); 44 1.1 mrg } 45 1.1 mrg 46 1.1 mrg box = isl_set_box_from_points(pt, pt2); 47 1.1 mrg 48 1.1 mrg return isl_set_intersect(set, box); 49 1.1 mrg } 50 1.1 mrg 51 1.1 mrg struct verify_point_bound { 52 1.1 mrg struct bound_options *options; 53 1.1 mrg int stride; 54 1.1 mrg int n; 55 1.1 mrg int exact; 56 1.1 mrg int error; 57 1.1 mrg 58 1.1 mrg isl_pw_qpolynomial_fold *pwf; 59 1.1 mrg isl_pw_qpolynomial_fold *bound; 60 1.1 mrg }; 61 1.1 mrg 62 1.1 mrg static isl_stat verify_point(__isl_take isl_point *pnt, void *user) 63 1.1 mrg { 64 1.1 mrg int i; 65 1.1 mrg isl_size nparam; 66 1.1 mrg struct verify_point_bound *vpb = (struct verify_point_bound *) user; 67 1.1 mrg isl_val *v; 68 1.1 mrg isl_ctx *ctx; 69 1.1 mrg isl_pw_qpolynomial_fold *pwf; 70 1.1 mrg isl_val *bound = NULL; 71 1.1 mrg isl_val *opt = NULL; 72 1.1 mrg isl_set *dom = NULL; 73 1.1 mrg isl_printer *p; 74 1.1 mrg const char *minmax; 75 1.1 mrg isl_bool bounded; 76 1.1 mrg int sign; 77 1.1 mrg int ok; 78 1.1 mrg FILE *out = vpb->options->print_all ? stdout : stderr; 79 1.1 mrg 80 1.1 mrg vpb->n--; 81 1.1 mrg 82 1.1 mrg if (1) { 83 1.1 mrg minmax = "ub"; 84 1.1 mrg sign = 1; 85 1.1 mrg } else { 86 1.1 mrg minmax = "lb"; 87 1.1 mrg sign = -1; 88 1.1 mrg } 89 1.1 mrg 90 1.1 mrg ctx = isl_point_get_ctx(pnt); 91 1.1 mrg p = isl_printer_to_file(ctx, out); 92 1.1 mrg 93 1.1 mrg pwf = isl_pw_qpolynomial_fold_copy(vpb->pwf); 94 1.1 mrg 95 1.1 mrg nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param); 96 1.1 mrg if (nparam < 0) 97 1.1 mrg pwf = isl_pw_qpolynomial_fold_free(pwf); 98 1.1 mrg for (i = 0; i < nparam; ++i) { 99 1.1 mrg v = isl_point_get_coordinate_val(pnt, isl_dim_param, i); 100 1.1 mrg pwf = isl_pw_qpolynomial_fold_fix_val(pwf, isl_dim_param, i, v); 101 1.1 mrg } 102 1.1 mrg 103 1.1 mrg bound = isl_pw_qpolynomial_fold_eval( 104 1.1 mrg isl_pw_qpolynomial_fold_copy(vpb->bound), 105 1.1 mrg isl_point_copy(pnt)); 106 1.1 mrg 107 1.1 mrg dom = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf)); 108 1.1 mrg bounded = isl_set_is_bounded(dom); 109 1.1 mrg 110 1.1 mrg if (bounded < 0) 111 1.1 mrg goto error; 112 1.1 mrg 113 1.1 mrg if (!bounded) 114 1.1 mrg opt = isl_pw_qpolynomial_fold_eval( 115 1.1 mrg isl_pw_qpolynomial_fold_copy(pwf), 116 1.1 mrg isl_set_sample_point(isl_set_copy(dom))); 117 1.1 mrg else if (sign > 0) 118 1.1 mrg opt = isl_pw_qpolynomial_fold_max(isl_pw_qpolynomial_fold_copy(pwf)); 119 1.1 mrg else 120 1.1 mrg opt = isl_pw_qpolynomial_fold_min(isl_pw_qpolynomial_fold_copy(pwf)); 121 1.1 mrg 122 1.1 mrg if (vpb->exact && bounded) 123 1.1 mrg ok = isl_val_eq(opt, bound); 124 1.1 mrg else if (sign > 0) 125 1.1 mrg ok = isl_val_le(opt, bound); 126 1.1 mrg else 127 1.1 mrg ok = isl_val_le(bound, opt); 128 1.1 mrg if (ok < 0) 129 1.1 mrg goto error; 130 1.1 mrg 131 1.1 mrg if (vpb->options->print_all || !ok) { 132 1.1 mrg p = isl_printer_print_str(p, minmax); 133 1.1 mrg p = isl_printer_print_str(p, "("); 134 1.1 mrg for (i = 0; i < nparam; ++i) { 135 1.1 mrg if (i) 136 1.1 mrg p = isl_printer_print_str(p, ", "); 137 1.1 mrg v = isl_point_get_coordinate_val(pnt, isl_dim_param, i); 138 1.1 mrg p = isl_printer_print_val(p, v); 139 1.1 mrg isl_val_free(v); 140 1.1 mrg } 141 1.1 mrg p = isl_printer_print_str(p, ") = "); 142 1.1 mrg p = isl_printer_print_val(p, bound); 143 1.1 mrg p = isl_printer_print_str(p, ", "); 144 1.1 mrg p = isl_printer_print_str(p, bounded ? "opt" : "sample"); 145 1.1 mrg p = isl_printer_print_str(p, " = "); 146 1.1 mrg p = isl_printer_print_val(p, opt); 147 1.1 mrg if (ok) 148 1.1 mrg p = isl_printer_print_str(p, ". OK"); 149 1.1 mrg else 150 1.1 mrg p = isl_printer_print_str(p, ". NOT OK"); 151 1.1 mrg p = isl_printer_end_line(p); 152 1.1 mrg } else if ((vpb->n % vpb->stride) == 0) { 153 1.1 mrg p = isl_printer_print_str(p, "o"); 154 1.1 mrg p = isl_printer_flush(p); 155 1.1 mrg } 156 1.1 mrg 157 1.1 mrg if (0) { 158 1.1 mrg error: 159 1.1 mrg ok = 0; 160 1.1 mrg } 161 1.1 mrg 162 1.1 mrg isl_pw_qpolynomial_fold_free(pwf); 163 1.1 mrg isl_val_free(bound); 164 1.1 mrg isl_val_free(opt); 165 1.1 mrg isl_point_free(pnt); 166 1.1 mrg isl_set_free(dom); 167 1.1 mrg 168 1.1 mrg isl_printer_free(p); 169 1.1 mrg 170 1.1 mrg if (!ok) 171 1.1 mrg vpb->error = 1; 172 1.1 mrg 173 1.1 mrg if (vpb->options->continue_on_error) 174 1.1 mrg ok = 1; 175 1.1 mrg 176 1.1 mrg return (vpb->n >= 1 && ok) ? isl_stat_ok : isl_stat_error; 177 1.1 mrg } 178 1.1 mrg 179 1.1 mrg static int check_solution(__isl_take isl_pw_qpolynomial_fold *pwf, 180 1.1 mrg __isl_take isl_pw_qpolynomial_fold *bound, int exact, 181 1.1 mrg struct bound_options *options) 182 1.1 mrg { 183 1.1 mrg struct verify_point_bound vpb; 184 1.1 mrg isl_int count, max; 185 1.1 mrg isl_set *dom; 186 1.1 mrg isl_set *context; 187 1.1 mrg int i, r, n; 188 1.1 mrg 189 1.1 mrg dom = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf)); 190 1.1 mrg context = isl_set_params(isl_set_copy(dom)); 191 1.1 mrg context = isl_set_remove_divs(context); 192 1.1 mrg context = set_bounds(context); 193 1.1 mrg 194 1.1 mrg isl_int_init(count); 195 1.1 mrg isl_int_init(max); 196 1.1 mrg 197 1.1 mrg isl_int_set_si(max, 200); 198 1.1 mrg r = isl_set_count_upto(context, max, &count); 199 1.1 mrg assert(r >= 0); 200 1.1 mrg n = isl_int_get_si(count); 201 1.1 mrg 202 1.1 mrg isl_int_clear(max); 203 1.1 mrg isl_int_clear(count); 204 1.1 mrg 205 1.1 mrg vpb.options = options; 206 1.1 mrg vpb.pwf = pwf; 207 1.1 mrg vpb.bound = bound; 208 1.1 mrg vpb.n = n; 209 1.1 mrg vpb.stride = n > 70 ? 1 + (n + 1)/70 : 1; 210 1.1 mrg vpb.error = 0; 211 1.1 mrg vpb.exact = exact; 212 1.1 mrg 213 1.1 mrg if (!options->print_all) { 214 1.1 mrg for (i = 0; i < vpb.n; i += vpb.stride) 215 1.1 mrg printf("."); 216 1.1 mrg printf("\r"); 217 1.1 mrg fflush(stdout); 218 1.1 mrg } 219 1.1 mrg 220 1.1 mrg isl_set_foreach_point(context, verify_point, &vpb); 221 1.1 mrg 222 1.1 mrg isl_set_free(context); 223 1.1 mrg isl_set_free(dom); 224 1.1 mrg isl_pw_qpolynomial_fold_free(pwf); 225 1.1 mrg isl_pw_qpolynomial_fold_free(bound); 226 1.1 mrg 227 1.1 mrg if (!options->print_all) 228 1.1 mrg printf("\n"); 229 1.1 mrg 230 1.1 mrg if (vpb.error) { 231 1.1 mrg fprintf(stderr, "Check failed !\n"); 232 1.1 mrg return -1; 233 1.1 mrg } 234 1.1 mrg 235 1.1 mrg return 0; 236 1.1 mrg } 237 1.1 mrg 238 1.1 mrg int main(int argc, char **argv) 239 1.1 mrg { 240 1.1 mrg isl_ctx *ctx; 241 1.1 mrg isl_pw_qpolynomial_fold *copy; 242 1.1 mrg isl_pw_qpolynomial_fold *pwf; 243 1.1 mrg isl_stream *s; 244 1.1 mrg struct isl_obj obj; 245 1.1 mrg struct bound_options *options; 246 1.1 mrg isl_bool exact; 247 1.1 mrg int r = 0; 248 1.1 mrg 249 1.1 mrg options = bound_options_new_with_defaults(); 250 1.1 mrg assert(options); 251 1.1 mrg argc = bound_options_parse(options, argc, argv, ISL_ARG_ALL); 252 1.1 mrg 253 1.1 mrg ctx = isl_ctx_alloc_with_options(&bound_options_args, options); 254 1.1 mrg 255 1.1 mrg s = isl_stream_new_file(ctx, stdin); 256 1.1 mrg obj = isl_stream_read_obj(s); 257 1.1 mrg if (obj.type == isl_obj_pw_qpolynomial) 258 1.1 mrg pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, 259 1.1 mrg obj.v); 260 1.1 mrg else if (obj.type == isl_obj_pw_qpolynomial_fold) 261 1.1 mrg pwf = obj.v; 262 1.1 mrg else { 263 1.1 mrg obj.type->free(obj.v); 264 1.1 mrg isl_die(ctx, isl_error_invalid, "invalid input", goto error); 265 1.1 mrg } 266 1.1 mrg 267 1.1 mrg if (options->verify) 268 1.1 mrg copy = isl_pw_qpolynomial_fold_copy(pwf); 269 1.1 mrg 270 1.1 mrg pwf = isl_pw_qpolynomial_fold_bound(pwf, &exact); 271 1.1 mrg pwf = isl_pw_qpolynomial_fold_coalesce(pwf); 272 1.1 mrg 273 1.1 mrg if (options->verify) { 274 1.1 mrg r = check_solution(copy, pwf, exact, options); 275 1.1 mrg } else { 276 1.1 mrg if (!exact) 277 1.1 mrg printf("# NOT exact\n"); 278 1.1 mrg isl_pw_qpolynomial_fold_print(pwf, stdout, 0); 279 1.1 mrg fprintf(stdout, "\n"); 280 1.1 mrg isl_pw_qpolynomial_fold_free(pwf); 281 1.1 mrg } 282 1.1 mrg 283 1.1 mrg error: 284 1.1 mrg isl_stream_free(s); 285 1.1 mrg 286 1.1 mrg isl_ctx_free(ctx); 287 1.1 mrg 288 1.1 mrg return r; 289 1.1 mrg } 290