6 #include <barvinok/barvinok.h>
10 #ifdef HAVE_SYS_TIMES_H
12 #include <sys/times.h>
14 typedef clock_t my_clock_t
;
16 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
18 return after
->tms_utime
- before
->tms_utime
;
23 typedef int my_clock_t
;
25 struct tms
{ int dummy
; };
26 static void times(struct tms
* time
)
29 static my_clock_t
time_diff(struct tms
*before
, struct tms
*after
)
41 { BV_APPROX_SIGN_NONE
, BV_APPROX_NONE
, 0 },
42 { BV_APPROX_SIGN_APPROX
, BV_APPROX_BERNOULLI
, 0 },
43 { BV_APPROX_SIGN_APPROX
, BV_APPROX_DROP
, 0 },
44 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
45 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
46 { BV_APPROX_SIGN_APPROX
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
47 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, 0 },
48 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
49 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
50 { BV_APPROX_SIGN_APPROX
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
51 { BV_APPROX_SIGN_LOWER
, BV_APPROX_DROP
, 0 },
52 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
53 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
54 { BV_APPROX_SIGN_LOWER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
55 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, 0 },
56 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
57 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
58 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
59 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
60 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
61 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
62 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
63 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
64 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
65 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
66 { BV_APPROX_SIGN_LOWER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
67 { BV_APPROX_SIGN_UPPER
, BV_APPROX_DROP
, 0 },
68 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_LIFT
},
69 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_VERTEX
},
70 { BV_APPROX_SIGN_UPPER
, BV_APPROX_VOLUME
, BV_VOL_BARYCENTER
},
71 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, 0 },
72 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_CHAMBER
},
73 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
},
74 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_CHAMBER
},
75 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
},
76 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
77 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
},
78 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW
| BV_APPROX_SCALE_CHAMBER
},
79 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
},
80 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
81 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
},
82 { BV_APPROX_SIGN_UPPER
, BV_APPROX_SCALE
, BV_APPROX_SCALE_FAST
| BV_APPROX_SCALE_NARROW2
| BV_APPROX_SCALE_CHAMBER
},
85 #define nr_methods (sizeof(methods)/sizeof(*methods))
89 struct verify_options
*verify
;
92 ISL_ARGS_START(struct options
, options_args
)
93 ISL_ARG_CHILD(struct options
, verify
, NULL
, &verify_options_args
, NULL
)
94 ISL_ARG_BOOL(struct options
, quiet
, 'q', "quiet", 0, NULL
)
97 ISL_ARG_DEF(options
, struct options
, options_args
)
101 double RE_sum
[nr_methods
];
103 my_clock_t ticks
[nr_methods
];
104 size_t size
[nr_methods
];
107 void result_data_init(struct result_data
*result
)
110 for (i
= 0; i
< nr_methods
; ++i
) {
111 result
->RE_sum
[i
] = 0;
112 result
->ticks
[i
] = 0;
115 value_init(result
->n
);
118 void result_data_clear(struct result_data
*result
)
121 value_clear(result
->n
);
124 void result_data_print(struct result_data
*result
, int n
)
128 fprintf(stderr
, "%g", (double)result
->ticks
[0]/n
);
129 for (i
= 1; i
< nr_methods
; ++i
)
130 fprintf(stderr
, ", %g", (double)result
->ticks
[i
]/n
);
131 fprintf(stderr
, "\n");
133 fprintf(stderr
, "%zd", result
->size
[0]/n
);
134 for (i
= 1; i
< nr_methods
; ++i
)
135 fprintf(stderr
, ", %zd", result
->size
[i
]/n
);
136 fprintf(stderr
, "\n");
138 fprintf(stderr
, "%g\n", VALUE_TO_DOUBLE(result
->n
));
139 fprintf(stderr
, "%g", result
->RE_sum
[0]/VALUE_TO_DOUBLE(result
->n
));
140 for (i
= 1; i
< nr_methods
; ++i
)
141 fprintf(stderr
, ", %g", result
->RE_sum
[i
]/VALUE_TO_DOUBLE(result
->n
));
142 fprintf(stderr
, "\n");
145 struct test_approx_data
{
146 struct verify_point_data vpd
;
147 isl_pw_qpolynomial
**pwqp
;
148 struct result_data
*result
;
151 static __isl_give isl_val
*eval(__isl_keep isl_pw_qpolynomial
*pwqp
,
152 __isl_keep isl_point
*pnt
, int sign
)
156 pwqp
= isl_pw_qpolynomial_copy(pwqp
);
157 res
= isl_pw_qpolynomial_eval(pwqp
, isl_point_copy(pnt
));
158 if (sign
== BV_APPROX_SIGN_LOWER
)
159 res
= isl_val_ceil(res
);
160 else if (sign
== BV_APPROX_SIGN_UPPER
)
161 res
= isl_val_floor(res
);
162 else if (sign
== BV_APPROX_SIGN_APPROX
)
163 res
= isl_val_trunc(res
);
165 assert(isl_val_is_int(res
));
170 static isl_stat
test_approx(__isl_take isl_point
*pnt
, void *user
)
172 struct test_approx_data
*ta_data
= (struct test_approx_data
*) user
;
173 isl_val
*exact
, *approx
;
178 exact
= eval(ta_data
->pwqp
[0], pnt
, BV_APPROX_SIGN_NONE
);
180 value_increment(ta_data
->result
->n
, ta_data
->result
->n
);
181 for (i
= 1; i
< nr_methods
; ++i
) {
183 approx
= eval(ta_data
->pwqp
[i
], pnt
, methods
[i
].sign
);
185 if (methods
[i
].sign
== BV_APPROX_SIGN_LOWER
)
186 assert(isl_val_le(approx
, exact
));
187 if (methods
[i
].sign
== BV_APPROX_SIGN_UPPER
)
188 assert(isl_val_ge(approx
, exact
));
189 approx
= isl_val_sub(approx
, isl_val_copy(exact
));
190 if (isl_val_is_zero(exact
))
191 error
= fabs(isl_val_get_d(approx
));
193 error
= fabs(isl_val_get_d(approx
)) / isl_val_get_d(exact
);
194 isl_val_free(approx
);
195 ta_data
->result
->RE_sum
[i
] += error
;
198 if (!ta_data
->vpd
.options
->print_all
&&
199 (ta_data
->vpd
.n
% ta_data
->vpd
.s
) == 0) {
207 return (ta_data
->vpd
.n
>= 1) ? isl_stat_ok
: isl_stat_error
;
210 static int test(__isl_keep isl_set
*context
,
211 __isl_keep isl_pw_qpolynomial
**pwqp
, struct result_data
*result
,
212 struct verify_options
*options
)
214 struct test_approx_data data
= { { options
} };
217 r
= verify_point_data_init(&data
.vpd
, context
);
220 data
.result
= result
;
222 isl_set_foreach_point(context
, &test_approx
, &data
);
226 verify_point_data_fini(&data
.vpd
);
231 /* Turn the set dimensions of "context" into parameters and return
232 * the corresponding parameter domain.
234 static __isl_give isl_set
*to_parameter_domain(__isl_take isl_set
*context
)
236 context
= isl_set_move_dims(context
, isl_dim_param
, 0, isl_dim_set
, 0,
237 isl_set_dim(context
, isl_dim_set
));
238 return isl_set_params(context
);
241 static int handle(isl_ctx
*ctx
, FILE *in
, struct result_data
*result
,
242 struct verify_options
*options
)
250 isl_pw_qpolynomial
*pwqp
[nr_methods
];
252 set
= isl_set_read_from_file(ctx
, in
);
253 context
= isl_set_read_from_file(ctx
, in
);
255 context
= to_parameter_domain(context
);
256 nparam
= isl_set_dim(context
, isl_dim_param
);
257 if (nparam
!= isl_set_dim(set
, isl_dim_param
)) {
258 int dim
= isl_set_dim(set
, isl_dim_set
);
259 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
260 isl_dim_set
, dim
- nparam
, nparam
);
263 set
= isl_set_intersect_params(set
, context
);
264 context
= isl_set_params(isl_set_copy(set
));
265 space
= isl_set_get_space(context
);
267 context
= verify_context_set_bounds(context
, options
);
269 for (i
= 0; i
< nr_methods
; ++i
) {
272 options
->barvinok
->approx
->approximation
= methods
[i
].sign
;
273 options
->barvinok
->approx
->method
= methods
[i
].method
;
274 if (methods
[i
].method
== BV_APPROX_SCALE
)
275 options
->barvinok
->approx
->scale_flags
= methods
[i
].flags
;
276 else if (methods
[i
].method
== BV_APPROX_VOLUME
)
277 options
->barvinok
->approx
->volume_triangulate
= methods
[i
].flags
;
280 pwqp
[i
] = isl_set_card(isl_set_copy(set
));
282 result
->ticks
[i
] = time_diff(&en_cpu
, &st_cpu
);
284 for (i
= 0; i
< nr_methods
; ++i
)
286 r
= test(context
, pwqp
, result
, options
);
287 for (i
= 0; i
< nr_methods
; ++i
)
288 isl_pw_qpolynomial_free(pwqp
[i
]);
290 isl_space_free(space
);
291 isl_set_free(context
);
297 int main(int argc
, char **argv
)
300 char path
[PATH_MAX
+1];
301 struct result_data all_result
;
303 int r
= EXIT_SUCCESS
;
304 struct options
*options
= options_new_with_defaults();
306 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
307 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
309 if (options
->verify
->M
== INT_MIN
)
310 options
->verify
->M
= 100;
311 if (options
->verify
->m
== INT_MAX
)
312 options
->verify
->m
= -100;
314 result_data_init(&all_result
);
316 while (fgets(path
, sizeof(path
), stdin
)) {
317 struct result_data result
;
322 result_data_init(&result
);
323 fprintf(stderr
, "%s", path
);
324 *strchr(path
, '\n') = '\0';
325 in
= fopen(path
, "r");
327 if (handle(ctx
, in
, &result
, options
->verify
) < 0)
332 result_data_print(&result
, 1);
334 value_addto(all_result
.n
, all_result
.n
, result
.n
);
335 for (i
= 0; i
< nr_methods
; ++i
) {
336 all_result
.RE_sum
[i
] += result
.RE_sum
[i
];
337 all_result
.ticks
[i
] += result
.ticks
[i
];
338 all_result
.size
[i
] += result
.size
[i
];
341 result_data_clear(&result
);
343 if (!options
->quiet
) {
344 fprintf(stderr
, "average\n");
345 result_data_print(&all_result
, n
);
349 result_data_clear(&all_result
);