5 #include <barvinok/barvinok.h>
9 #ifdef HAVE_SYS_TIMES_H
11 #include <sys/times.h>
13 typedef clock_t my_clock_t
;
15 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
17 return after
->tms_utime
- before
->tms_utime
;
22 typedef int my_clock_t
;
24 struct tms
{ int dummy
; };
25 static void times(struct tms
* time
)
28 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
40 { BV_APPROX_SIGN_NONE
, BV_APPROX_NONE
, 0 },
41 { BV_APPROX_SIGN_APPROX
, BV_APPROX_BERNOULLI
, 0 },
42 { BV_APPROX_SIGN_APPROX
, BV_APPROX_DROP
, 0 },
43 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
44 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
45 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
46 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, 0 },
47 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
48 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
49 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
50 { BV_APPROX_SIGN_LOWER
, BV_APPROX_DROP
, 0 },
51 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
52 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
53 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
54 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, 0 },
55 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
56 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
57 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
58 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
59 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
60 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
61 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
62 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
63 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
64 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
65 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
66 { BV_APPROX_SIGN_UPPER
, BV_APPROX_DROP
, 0 },
67 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
68 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
69 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
70 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, 0 },
71 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
72 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
73 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
74 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
75 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
76 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
77 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
78 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
79 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
80 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
81 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
84 #define nr_methods (sizeof(methods)/sizeof(*methods))
88 struct verify_options
*verify
;
91 ISL_ARGS_START(struct options
, options_args
)
92 ISL_ARG_CHILD(struct options
, verify
, NULL
, &verify_options_args
, NULL
)
93 ISL_ARG_BOOL(struct options
, quiet
, 'q', "quiet", 0, NULL
)
96 ISL_ARG_DEF(options
, struct options
, options_args
)
100 double RE_sum
[nr_methods
];
102 my_clock_t ticks
[nr_methods
];
103 size_t size
[nr_methods
];
106 void result_data_init(struct result_data
*result
)
109 for (i
= 0; i
< nr_methods
; ++i
) {
110 result
->RE_sum
[i
] = 0;
111 result
->ticks
[i
] = 0;
114 value_init(result
->n
);
117 void result_data_clear(struct result_data
*result
)
120 value_clear(result
->n
);
123 void result_data_print(struct result_data
*result
, int n
)
127 fprintf(stderr
, "%g", (double)result
->ticks
[0]/n
);
128 for (i
= 1; i
< nr_methods
; ++i
)
129 fprintf(stderr
, ", %g", (double)result
->ticks
[i
]/n
);
130 fprintf(stderr
, "\n");
132 fprintf(stderr
, "%zd", result
->size
[0]/n
);
133 for (i
= 1; i
< nr_methods
; ++i
)
134 fprintf(stderr
, ", %zd", result
->size
[i
]/n
);
135 fprintf(stderr
, "\n");
137 fprintf(stderr
, "%g\n", VALUE_TO_DOUBLE(result
->n
));
138 fprintf(stderr
, "%g", result
->RE_sum
[0]/VALUE_TO_DOUBLE(result
->n
));
139 for (i
= 1; i
< nr_methods
; ++i
)
140 fprintf(stderr
, ", %g", result
->RE_sum
[i
]/VALUE_TO_DOUBLE(result
->n
));
141 fprintf(stderr
, "\n");
144 struct test_approx_data
{
145 struct verify_point_data vpd
;
146 isl_pw_qpolynomial
**pwqp
;
147 struct result_data
*result
;
150 static __isl_give isl_val
*eval(__isl_keep isl_pw_qpolynomial
*pwqp
,
151 __isl_keep isl_point
*pnt
, int sign
)
155 pwqp
= isl_pw_qpolynomial_copy(pwqp
);
156 res
= isl_pw_qpolynomial_eval(pwqp
, isl_point_copy(pnt
));
157 if (sign
== BV_APPROX_SIGN_LOWER
)
158 res
= isl_val_ceil(res
);
159 else if (sign
== BV_APPROX_SIGN_UPPER
)
160 res
= isl_val_floor(res
);
161 else if (sign
== BV_APPROX_SIGN_APPROX
)
162 res
= isl_val_trunc(res
);
164 assert(isl_val_is_int(res
));
169 static int test_approx(__isl_take isl_point
*pnt
, void *user
)
171 struct test_approx_data
*ta_data
= (struct test_approx_data
*) user
;
172 isl_val
*exact
, *approx
;
177 exact
= eval(ta_data
->pwqp
[0], pnt
, BV_APPROX_SIGN_NONE
);
179 value_increment(ta_data
->result
->n
, ta_data
->result
->n
);
180 for (i
= 1; i
< nr_methods
; ++i
) {
182 approx
= eval(ta_data
->pwqp
[i
], pnt
, methods
[i
].sign
);
183 if (methods
[i
].sign
== BV_APPROX_SIGN_LOWER
)
184 assert(isl_val_le(approx
, exact
));
185 if (methods
[i
].sign
== BV_APPROX_SIGN_UPPER
)
186 assert(isl_val_ge(approx
, exact
));
187 approx
= isl_val_sub(approx
, isl_val_copy(exact
));
188 if (isl_val_is_zero(exact
))
189 error
= abs(isl_val_get_d(approx
));
191 error
= abs(isl_val_get_d(approx
)) / isl_val_get_d(exact
);
192 isl_val_free(approx
);
193 ta_data
->result
->RE_sum
[i
] += error
;
196 if (!ta_data
->vpd
.options
->print_all
&&
197 (ta_data
->vpd
.n
% ta_data
->vpd
.s
) == 0) {
205 return (ta_data
->vpd
.n
>= 1) ? 0 : -1;
208 static int test(__isl_keep isl_set
*context
,
209 __isl_keep isl_pw_qpolynomial
**pwqp
, struct result_data
*result
,
210 struct verify_options
*options
)
212 struct test_approx_data data
= { { options
} };
215 r
= verify_point_data_init(&data
.vpd
, context
);
218 data
.result
= result
;
220 isl_set_foreach_point(context
, &test_approx
, &data
);
224 verify_point_data_fini(&data
.vpd
);
229 /* Turn the set dimensions of "context" into parameters and return
230 * the corresponding parameter domain.
232 static __isl_give isl_set
*to_parameter_domain(__isl_take isl_set
*context
)
234 context
= isl_set_move_dims(context
, isl_dim_param
, 0, isl_dim_set
, 0,
235 isl_set_dim(context
, isl_dim_set
));
236 return isl_set_params(context
);
239 static int handle(isl_ctx
*ctx
, FILE *in
, struct result_data
*result
,
240 struct verify_options
*options
)
248 isl_pw_qpolynomial
*pwqp
[nr_methods
];
250 set
= isl_set_read_from_file(ctx
, in
);
251 context
= isl_set_read_from_file(ctx
, in
);
253 context
= to_parameter_domain(context
);
254 nparam
= isl_set_dim(context
, isl_dim_param
);
255 if (nparam
!= isl_set_dim(set
, isl_dim_param
)) {
256 int dim
= isl_set_dim(set
, isl_dim_set
);
257 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
258 isl_dim_set
, dim
- nparam
, nparam
);
261 set
= isl_set_intersect_params(set
, context
);
262 context
= isl_set_params(isl_set_copy(set
));
263 space
= isl_set_get_space(context
);
265 context
= verify_context_set_bounds(context
, options
);
267 for (i
= 0; i
< nr_methods
; ++i
) {
270 options
->barvinok
->approx
->approximation
= methods
[i
].sign
;
271 options
->barvinok
->approx
->method
= methods
[i
].method
;
272 if (methods
[i
].method
== BV_APPROX_SCALE
)
273 options
->barvinok
->approx
->scale_flags
= methods
[i
].flags
;
274 else if (methods
[i
].method
== BV_APPROX_VOLUME
)
275 options
->barvinok
->approx
->volume_triangulate
= methods
[i
].flags
;
278 pwqp
[i
] = isl_set_card(isl_set_copy(set
));
280 result
->ticks
[i
] = time_diff(&en_cpu
, &st_cpu
);
282 for (i
= 0; i
< nr_methods
; ++i
)
284 r
= test(context
, pwqp
, result
, options
);
285 for (i
= 0; i
< nr_methods
; ++i
)
286 isl_pw_qpolynomial_free(pwqp
[i
]);
288 isl_space_free(space
);
289 isl_set_free(context
);
295 int main(int argc
, char **argv
)
298 char path
[PATH_MAX
+1];
299 struct result_data all_result
;
301 int r
= EXIT_SUCCESS
;
302 struct options
*options
= options_new_with_defaults();
304 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
305 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
307 if (options
->verify
->M
== INT_MIN
)
308 options
->verify
->M
= 100;
309 if (options
->verify
->m
== INT_MAX
)
310 options
->verify
->m
= -100;
312 result_data_init(&all_result
);
314 while (fgets(path
, sizeof(path
), stdin
)) {
315 struct result_data result
;
320 result_data_init(&result
);
321 fprintf(stderr
, "%s", path
);
322 *strchr(path
, '\n') = '\0';
323 in
= fopen(path
, "r");
325 if (handle(ctx
, in
, &result
, options
->verify
) < 0)
330 result_data_print(&result
, 1);
332 value_addto(all_result
.n
, all_result
.n
, result
.n
);
333 for (i
= 0; i
< nr_methods
; ++i
) {
334 all_result
.RE_sum
[i
] += result
.RE_sum
[i
];
335 all_result
.ticks
[i
] += result
.ticks
[i
];
336 all_result
.size
[i
] += result
.size
[i
];
339 result_data_clear(&result
);
341 if (!options
->quiet
) {
342 fprintf(stderr
, "average\n");
343 result_data_print(&all_result
, n
);
347 result_data_clear(&all_result
);