11 #include <isl/polynomial.h>
12 #include <barvinok/polylib.h>
13 #include <barvinok/isl.h>
14 #include <barvinok/options.h>
18 #ifdef HAVE_SYS_TIMES_H
20 #include <sys/times.h>
22 typedef clock_t my_clock_t
;
24 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
26 return after
->tms_utime
- before
->tms_utime
;
31 typedef int my_clock_t
;
33 struct tms
{ int dummy
; };
34 static void times(struct tms
* time
)
37 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
49 { BV_APPROX_SIGN_NONE
, BV_APPROX_NONE
, 0 },
50 { BV_APPROX_SIGN_APPROX
, BV_APPROX_BERNOULLI
, 0 },
51 { BV_APPROX_SIGN_APPROX
, BV_APPROX_DROP
, 0 },
52 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
53 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
54 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
55 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, 0 },
56 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
57 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
58 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
59 { BV_APPROX_SIGN_LOWER
, BV_APPROX_DROP
, 0 },
60 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
61 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
62 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
63 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, 0 },
64 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
65 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
66 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
67 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
68 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
69 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
70 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
71 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
72 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
73 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
74 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
75 { BV_APPROX_SIGN_UPPER
, BV_APPROX_DROP
, 0 },
76 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
77 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
78 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
79 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, 0 },
80 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
81 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
82 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
83 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
84 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
85 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
86 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
87 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
88 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
89 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
90 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
93 #define nr_methods (sizeof(methods)/sizeof(*methods))
97 struct verify_options
*verify
;
100 ISL_ARGS_START(struct options
, options_args
)
101 ISL_ARG_CHILD(struct options
, verify
, NULL
, &verify_options_args
, NULL
)
102 ISL_ARG_BOOL(struct options
, quiet
, 'q', "quiet", 0, NULL
)
105 ISL_ARG_DEF(options
, struct options
, options_args
)
109 double RE_sum
[nr_methods
];
111 my_clock_t ticks
[nr_methods
];
112 size_t size
[nr_methods
];
115 void result_data_init(struct result_data
*result
)
118 for (i
= 0; i
< nr_methods
; ++i
) {
119 result
->RE_sum
[i
] = 0;
120 result
->ticks
[i
] = 0;
123 value_init(result
->n
);
126 void result_data_clear(struct result_data
*result
)
128 value_clear(result
->n
);
131 void result_data_print(struct result_data
*result
, int n
)
135 fprintf(stderr
, "%g", (double)result
->ticks
[0]/n
);
136 for (i
= 1; i
< nr_methods
; ++i
)
137 fprintf(stderr
, ", %g", (double)result
->ticks
[i
]/n
);
138 fprintf(stderr
, "\n");
140 fprintf(stderr
, "%zd", result
->size
[0]/n
);
141 for (i
= 1; i
< nr_methods
; ++i
)
142 fprintf(stderr
, ", %zd", result
->size
[i
]/n
);
143 fprintf(stderr
, "\n");
145 fprintf(stderr
, "%g\n", VALUE_TO_DOUBLE(result
->n
));
146 fprintf(stderr
, "%g", result
->RE_sum
[0]/VALUE_TO_DOUBLE(result
->n
));
147 for (i
= 1; i
< nr_methods
; ++i
)
148 fprintf(stderr
, ", %g", result
->RE_sum
[i
]/VALUE_TO_DOUBLE(result
->n
));
149 fprintf(stderr
, "\n");
152 struct test_approx_data
{
153 struct verify_point_data vpd
;
154 isl_pw_qpolynomial
**pwqp
;
155 struct result_data
*result
;
158 static __isl_give isl_val
*eval(__isl_keep isl_pw_qpolynomial
*pwqp
,
159 __isl_keep isl_point
*pnt
, int sign
)
163 pwqp
= isl_pw_qpolynomial_copy(pwqp
);
164 res
= isl_pw_qpolynomial_eval(pwqp
, isl_point_copy(pnt
));
165 if (sign
== BV_APPROX_SIGN_LOWER
)
166 res
= isl_val_ceil(res
);
167 else if (sign
== BV_APPROX_SIGN_UPPER
)
168 res
= isl_val_floor(res
);
169 else if (sign
== BV_APPROX_SIGN_APPROX
)
170 res
= isl_val_trunc(res
);
172 assert(isl_val_is_int(res
));
177 static isl_stat
test_approx(__isl_take isl_point
*pnt
, void *user
)
179 struct test_approx_data
*ta_data
= (struct test_approx_data
*) user
;
180 isl_val
*exact
, *approx
;
185 exact
= eval(ta_data
->pwqp
[0], pnt
, BV_APPROX_SIGN_NONE
);
187 value_increment(ta_data
->result
->n
, ta_data
->result
->n
);
188 for (i
= 1; i
< nr_methods
; ++i
) {
190 approx
= eval(ta_data
->pwqp
[i
], pnt
, methods
[i
].sign
);
192 if (methods
[i
].sign
== BV_APPROX_SIGN_LOWER
)
193 assert(isl_val_le(approx
, exact
));
194 if (methods
[i
].sign
== BV_APPROX_SIGN_UPPER
)
195 assert(isl_val_ge(approx
, exact
));
196 approx
= isl_val_sub(approx
, isl_val_copy(exact
));
197 if (isl_val_is_zero(exact
))
198 error
= fabs(isl_val_get_d(approx
));
200 error
= fabs(isl_val_get_d(approx
)) / isl_val_get_d(exact
);
201 isl_val_free(approx
);
202 ta_data
->result
->RE_sum
[i
] += error
;
205 if (!ta_data
->vpd
.options
->print_all
&&
206 (ta_data
->vpd
.n
% ta_data
->vpd
.s
) == 0) {
214 return (ta_data
->vpd
.n
>= 1) ? isl_stat_ok
: isl_stat_error
;
217 static int test(__isl_keep isl_set
*context
,
218 __isl_keep isl_pw_qpolynomial
**pwqp
, struct result_data
*result
,
219 struct verify_options
*options
)
221 struct test_approx_data data
= { { options
} };
224 r
= verify_point_data_init(&data
.vpd
, context
);
227 data
.result
= result
;
229 isl_set_foreach_point(context
, &test_approx
, &data
);
233 verify_point_data_fini(&data
.vpd
);
238 /* Turn the set dimensions of "context" into parameters and return
239 * the corresponding parameter domain.
241 static __isl_give isl_set
*to_parameter_domain(__isl_take isl_set
*context
)
243 context
= isl_set_move_dims(context
, isl_dim_param
, 0, isl_dim_set
, 0,
244 isl_set_dim(context
, isl_dim_set
));
245 return isl_set_params(context
);
248 static int handle(isl_ctx
*ctx
, FILE *in
, struct result_data
*result
,
249 struct verify_options
*options
)
257 isl_pw_qpolynomial
*pwqp
[nr_methods
];
259 set
= isl_set_read_from_file(ctx
, in
);
260 context
= isl_set_read_from_file(ctx
, in
);
262 context
= to_parameter_domain(context
);
263 nparam
= isl_set_dim(context
, isl_dim_param
);
264 if (nparam
!= isl_set_dim(set
, isl_dim_param
)) {
265 int dim
= isl_set_dim(set
, isl_dim_set
);
266 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
267 isl_dim_set
, dim
- nparam
, nparam
);
270 set
= isl_set_intersect_params(set
, context
);
271 context
= isl_set_params(isl_set_copy(set
));
272 space
= isl_set_get_space(context
);
274 context
= verify_context_set_bounds(context
, options
);
276 for (i
= 0; i
< nr_methods
; ++i
) {
279 options
->barvinok
->approx
->approximation
= methods
[i
].sign
;
280 options
->barvinok
->approx
->method
= methods
[i
].method
;
281 if (methods
[i
].method
== BV_APPROX_SCALE
)
282 options
->barvinok
->approx
->scale_flags
= methods
[i
].flags
;
283 else if (methods
[i
].method
== BV_APPROX_VOLUME
)
284 options
->barvinok
->approx
->volume_triangulate
= methods
[i
].flags
;
287 pwqp
[i
] = isl_set_card(isl_set_copy(set
));
289 result
->ticks
[i
] = time_diff(&en_cpu
, &st_cpu
);
291 for (i
= 0; i
< nr_methods
; ++i
)
293 r
= test(context
, pwqp
, result
, options
);
294 for (i
= 0; i
< nr_methods
; ++i
)
295 isl_pw_qpolynomial_free(pwqp
[i
]);
297 isl_space_free(space
);
298 isl_set_free(context
);
304 int main(int argc
, char **argv
)
307 char path
[PATH_MAX
+1];
308 struct result_data all_result
;
310 int r
= EXIT_SUCCESS
;
311 struct options
*options
= options_new_with_defaults();
313 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
314 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
316 if (options
->verify
->M
== INT_MIN
)
317 options
->verify
->M
= 100;
318 if (options
->verify
->m
== INT_MAX
)
319 options
->verify
->m
= -100;
321 result_data_init(&all_result
);
323 while (fgets(path
, sizeof(path
), stdin
)) {
324 struct result_data result
;
329 result_data_init(&result
);
330 fprintf(stderr
, "%s", path
);
331 *strchr(path
, '\n') = '\0';
332 in
= fopen(path
, "r");
334 if (handle(ctx
, in
, &result
, options
->verify
) < 0)
339 result_data_print(&result
, 1);
341 value_addto(all_result
.n
, all_result
.n
, result
.n
);
342 for (i
= 0; i
< nr_methods
; ++i
) {
343 all_result
.RE_sum
[i
] += result
.RE_sum
[i
];
344 all_result
.ticks
[i
] += result
.ticks
[i
];
345 all_result
.size
[i
] += result
.size
[i
];
348 result_data_clear(&result
);
350 if (!options
->quiet
) {
351 fprintf(stderr
, "average\n");
352 result_data_print(&all_result
, n
);
356 result_data_clear(&all_result
);