9 #include "idct_reference.h"
10 #include "idct_float.h"
11 #include "idct_imprecise_int.h"
13 // Generate random coefficients in the range [-15..15].
14 void gen_random_coeffs(int16_t* dst, size_t len)
16 // Standard NR LCG (we avoid rand() to get consistent behavior across platforms).
17 static uint32_t seed = 1234;
18 for (unsigned i = 0; i < len; ++i) {
19 seed = seed * 1664525U + 1013904223U;
21 dst[i] = (uint8_t)(seed >> 27) & 0x7;
23 dst[i] = -((uint8_t)(seed >> 27) & 0x7);
28 // Test that the input is pretty close to the reference for random inputs.
29 // (If the reference funtion is given in, this becomes a simple test of its
31 void test_random_inputs(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
33 int16_t coeff[DCTSIZE2];
34 uint32_t quant[DCTSIZE2];
35 uint8_t output[DCTSIZE2];
36 uint8_t reference[DCTSIZE2];
38 // Unit quantization (ie., no scaling).
39 for (unsigned i = 0; i < DCTSIZE2; ++i) {
43 void* userdata_reference = idct_reference_alloc(quant);
44 void* userdata = idct_alloc(quant);
46 for (unsigned i = 0; i < 1000; ++i) {
47 gen_random_coeffs(coeff, DCTSIZE2);
49 (*idct)(coeff, userdata, output);
50 (idct_reference)(coeff, userdata_reference, reference);
52 // Find the RMS difference.
54 for (unsigned i = 0; i < DCTSIZE2; ++i) {
55 diff_squared += (output[i] - reference[i]) * (output[i] - reference[i]);
58 assert(diff_squared <= 5);
61 idct_reference_free(userdata_reference);
65 // Test that a single DC coefficient becomes spread out to all blocks.
66 void test_dc_becomes_spread_out(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
68 int16_t coeff[DCTSIZE2] = { 0 };
69 uint32_t quant[DCTSIZE2];
70 uint8_t output[DCTSIZE2];
72 // Unit quantization (ie., no scaling).
73 for (unsigned i = 0; i < DCTSIZE2; ++i) {
77 void* userdata = idct_alloc(quant);
79 for (unsigned i = -255*8; i < 255*16; ++i) {
80 int reference_value = i / 8 + 128;
81 if (reference_value < 0) {
83 } else if (reference_value > 255) {
84 reference_value = 255;
88 (*idct)(coeff, userdata, output);
90 for (unsigned i = 0; i < DCTSIZE2; ++i) {
91 assert(abs(output[i] - reference_value) <= 1);
98 double timediff(const struct timeval* a, const struct timeval* b)
100 return (double)(b->tv_sec - a->tv_sec) +
101 (double)(b->tv_usec - a->tv_usec) * 1e-6;
104 void test_performance(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
106 const unsigned num_runs = (idct == idct_reference) ? 5000 : 5000000;
108 int16_t coeff[DCTSIZE2];
109 uint32_t quant[DCTSIZE2];
110 uint8_t output[DCTSIZE2];
112 gen_random_coeffs(coeff, DCTSIZE2);
114 // Unit quantization (ie., no scaling).
115 for (unsigned i = 0; i < DCTSIZE2; ++i) {
119 void* userdata = idct_alloc(quant);
121 start_benchmark_timer();
123 for (unsigned i = 0; i < num_runs; ++i) {
124 (*idct)(coeff, userdata, output);
127 double diff = stop_benchmark_timer();
128 printf("%u runs in %.2f CPU seconds = %.2f IDCTs/sec\n",
129 num_runs, diff, num_runs / diff);
134 void test_all_idct(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
136 printf(" test_dc_becomes_spread_out()\n");
137 test_dc_becomes_spread_out(idct_alloc, idct_free, idct);
139 printf(" test_random_inputs()\n");
140 test_random_inputs(idct_alloc, idct_free, idct);
142 printf(" performance test: ");
143 test_performance(idct_alloc, idct_free, idct);
148 printf("idct_reference:\n");
149 test_all_idct(idct_reference_alloc, idct_reference_free, idct_reference);
151 printf("idct_float:\n");
152 test_all_idct(idct_float_alloc, idct_float_free, idct_float);
154 printf("idct_imprecise_int:\n");
155 test_all_idct(idct_imprecise_int_alloc, idct_imprecise_int_free, idct_imprecise_int);
157 printf("All tests pass.\n");