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
);
184 if (methods
[i
].sign
== BV_APPROX_SIGN_LOWER
)
185 assert(isl_val_le(approx
, exact
));
186 if (methods
[i
].sign
== BV_APPROX_SIGN_UPPER
)
187 assert(isl_val_ge(approx
, exact
));
188 approx
= isl_val_sub(approx
, isl_val_copy(exact
));
189 if (isl_val_is_zero(exact
))
190 error
= fabs(isl_val_get_d(approx
));
192 error
= fabs(isl_val_get_d(approx
)) / isl_val_get_d(exact
);
193 isl_val_free(approx
);
194 ta_data
->result
->RE_sum
[i
] += error
;
197 if (!ta_data
->vpd
.options
->print_all
&&
198 (ta_data
->vpd
.n
% ta_data
->vpd
.s
) == 0) {
206 return (ta_data
->vpd
.n
>= 1) ? isl_stat_ok
: isl_stat_error
;
209 static int test(__isl_keep isl_set
*context
,
210 __isl_keep isl_pw_qpolynomial
**pwqp
, struct result_data
*result
,
211 struct verify_options
*options
)
213 struct test_approx_data data
= { { options
} };
216 r
= verify_point_data_init(&data
.vpd
, context
);
219 data
.result
= result
;
221 isl_set_foreach_point(context
, &test_approx
, &data
);
225 verify_point_data_fini(&data
.vpd
);
230 /* Turn the set dimensions of "context" into parameters and return
231 * the corresponding parameter domain.
233 static __isl_give isl_set
*to_parameter_domain(__isl_take isl_set
*context
)
235 context
= isl_set_move_dims(context
, isl_dim_param
, 0, isl_dim_set
, 0,
236 isl_set_dim(context
, isl_dim_set
));
237 return isl_set_params(context
);
240 static int handle(isl_ctx
*ctx
, FILE *in
, struct result_data
*result
,
241 struct verify_options
*options
)
249 isl_pw_qpolynomial
*pwqp
[nr_methods
];
251 set
= isl_set_read_from_file(ctx
, in
);
252 context
= isl_set_read_from_file(ctx
, in
);
254 context
= to_parameter_domain(context
);
255 nparam
= isl_set_dim(context
, isl_dim_param
);
256 if (nparam
!= isl_set_dim(set
, isl_dim_param
)) {
257 int dim
= isl_set_dim(set
, isl_dim_set
);
258 set
= isl_set_move_dims(set
, isl_dim_param
, 0,
259 isl_dim_set
, dim
- nparam
, nparam
);
262 set
= isl_set_intersect_params(set
, context
);
263 context
= isl_set_params(isl_set_copy(set
));
264 space
= isl_set_get_space(context
);
266 context
= verify_context_set_bounds(context
, options
);
268 for (i
= 0; i
< nr_methods
; ++i
) {
271 options
->barvinok
->approx
->approximation
= methods
[i
].sign
;
272 options
->barvinok
->approx
->method
= methods
[i
].method
;
273 if (methods
[i
].method
== BV_APPROX_SCALE
)
274 options
->barvinok
->approx
->scale_flags
= methods
[i
].flags
;
275 else if (methods
[i
].method
== BV_APPROX_VOLUME
)
276 options
->barvinok
->approx
->volume_triangulate
= methods
[i
].flags
;
279 pwqp
[i
] = isl_set_card(isl_set_copy(set
));
281 result
->ticks
[i
] = time_diff(&en_cpu
, &st_cpu
);
283 for (i
= 0; i
< nr_methods
; ++i
)
285 r
= test(context
, pwqp
, result
, options
);
286 for (i
= 0; i
< nr_methods
; ++i
)
287 isl_pw_qpolynomial_free(pwqp
[i
]);
289 isl_space_free(space
);
290 isl_set_free(context
);
296 int main(int argc
, char **argv
)
299 char path
[PATH_MAX
+1];
300 struct result_data all_result
;
302 int r
= EXIT_SUCCESS
;
303 struct options
*options
= options_new_with_defaults();
305 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
306 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
308 if (options
->verify
->M
== INT_MIN
)
309 options
->verify
->M
= 100;
310 if (options
->verify
->m
== INT_MAX
)
311 options
->verify
->m
= -100;
313 result_data_init(&all_result
);
315 while (fgets(path
, sizeof(path
), stdin
)) {
316 struct result_data result
;
321 result_data_init(&result
);
322 fprintf(stderr
, "%s", path
);
323 *strchr(path
, '\n') = '\0';
324 in
= fopen(path
, "r");
326 if (handle(ctx
, in
, &result
, options
->verify
) < 0)
331 result_data_print(&result
, 1);
333 value_addto(all_result
.n
, all_result
.n
, result
.n
);
334 for (i
= 0; i
< nr_methods
; ++i
) {
335 all_result
.RE_sum
[i
] += result
.RE_sum
[i
];
336 all_result
.ticks
[i
] += result
.ticks
[i
];
337 all_result
.size
[i
] += result
.size
[i
];
340 result_data_clear(&result
);
342 if (!options
->quiet
) {
343 fprintf(stderr
, "average\n");
344 result_data_print(&all_result
, n
);
348 result_data_clear(&all_result
);