#include <stdlib.h>
#include <math.h>
#include <assert.h>
-#include <time.h>
-#include <sys/time.h>
+#include "benchmark.h"
#include "idct.h"
+#include "idct_reference.h"
+#include "idct_float.h"
+#include "idct_imprecise_int.h"
// Generate random coefficients in the range [-15..15].
void gen_random_coeffs(int16_t* dst, size_t len)
// Test that the input is pretty close to the reference for random inputs.
// (If the reference funtion is given in, this becomes a simple test of its
// determinism.)
-void test_random_inputs(idct_func_t* idct)
+void test_random_inputs(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
{
int16_t coeff[DCTSIZE2];
uint32_t quant[DCTSIZE2];
uint8_t output[DCTSIZE2];
uint8_t reference[DCTSIZE2];
-
+
// Unit quantization (ie., no scaling).
for (unsigned i = 0; i < DCTSIZE2; ++i) {
quant[i] = 1;
}
+
+ void* userdata_reference = idct_reference_alloc(quant);
+ void* userdata = idct_alloc(quant);
for (unsigned i = 0; i < 1000; ++i) {
gen_random_coeffs(coeff, DCTSIZE2);
- (*idct)(coeff, quant, output);
- (idct_reference)(coeff, quant, reference);
+ (*idct)(coeff, userdata, output);
+ (idct_reference)(coeff, userdata_reference, reference);
// Find the RMS difference.
int diff_squared = 0;
assert(diff_squared <= 5);
}
+
+ idct_reference_free(userdata_reference);
+ idct_free(userdata);
}
// Test that a single DC coefficient becomes spread out to all blocks.
-void test_dc_becomes_spread_out(idct_func_t* idct)
+void test_dc_becomes_spread_out(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
{
int16_t coeff[DCTSIZE2] = { 0 };
uint32_t quant[DCTSIZE2];
uint8_t output[DCTSIZE2];
-
+
// Unit quantization (ie., no scaling).
for (unsigned i = 0; i < DCTSIZE2; ++i) {
quant[i] = 1;
}
- for (unsigned i = 0; i < 255*8; ++i) {
- uint32_t reference_value = i / 8;
+ void* userdata = idct_alloc(quant);
+
+ for (unsigned i = -255*8; i < 255*16; ++i) {
+ int reference_value = i / 8 + 128;
+ if (reference_value < 0) {
+ reference_value = 0;
+ } else if (reference_value > 255) {
+ reference_value = 255;
+ }
coeff[0] = i;
- (*idct)(coeff, quant, output);
+ (*idct)(coeff, userdata, output);
for (unsigned i = 0; i < DCTSIZE2; ++i) {
assert(abs(output[i] - reference_value) <= 1);
}
}
+
+ idct_free(userdata);
}
double timediff(const struct timeval* a, const struct timeval* b)
(double)(b->tv_usec - a->tv_usec) * 1e-6;
}
-void test_performance(idct_func_t* idct)
+void test_performance(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
{
const unsigned num_runs = (idct == idct_reference) ? 5000 : 5000000;
quant[i] = 1;
}
- struct timeval start, now;
- gettimeofday(&start, NULL);
+ void* userdata = idct_alloc(quant);
+
+ start_benchmark_timer();
for (unsigned i = 0; i < num_runs; ++i) {
- (*idct)(coeff, quant, output);
+ (*idct)(coeff, userdata, output);
}
- gettimeofday(&now, NULL);
-
- double diff = timediff(&start, &now);
- printf("%u runs in %.2f seconds = %.2f DCTs/sec\n",
+ double diff = stop_benchmark_timer();
+ printf("%u runs in %.2f CPU seconds = %.2f IDCTs/sec\n",
num_runs, diff, num_runs / diff);
+
+ idct_free(userdata);
}
-void test_all_idct(idct_func_t* idct)
+void test_all_idct(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
{
printf(" test_dc_becomes_spread_out()\n");
- test_dc_becomes_spread_out(idct);
+ test_dc_becomes_spread_out(idct_alloc, idct_free, idct);
printf(" test_random_inputs()\n");
- test_random_inputs(idct);
+ test_random_inputs(idct_alloc, idct_free, idct);
printf(" performance test: ");
- test_performance(idct);
+ test_performance(idct_alloc, idct_free, idct);
}
int main(void)
{
printf("idct_reference:\n");
- test_all_idct(idct_reference);
+ test_all_idct(idct_reference_alloc, idct_reference_free, idct_reference);
+
+ printf("idct_float:\n");
+ test_all_idct(idct_float_alloc, idct_float_free, idct_float);
+
+ printf("idct_imprecise_int:\n");
+ test_all_idct(idct_imprecise_int_alloc, idct_imprecise_int_free, idct_imprecise_int);
printf("All tests pass.\n");
return 0;