10 // Generate random coefficients in the range [-15..15].
11 void gen_random_coeffs(int16_t* dst, size_t len)
13 // Standard NR LCG (we avoid rand() to get consistent behavior across platforms).
14 static uint32_t seed = 1234;
15 for (unsigned i = 0; i < len; ++i) {
16 seed = seed * 1664525U + 1013904223U;
18 dst[i] = (uint8_t)(seed >> 27) & 0x7;
20 dst[i] = -((uint8_t)(seed >> 27) & 0x7);
25 // Test that the input is pretty close to the reference for random inputs.
26 // (If the reference funtion is given in, this becomes a simple test of its
28 void test_random_inputs(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
30 int16_t coeff[DCTSIZE2];
31 uint32_t quant[DCTSIZE2];
32 uint8_t output[DCTSIZE2];
33 uint8_t reference[DCTSIZE2];
35 // Unit quantization (ie., no scaling).
36 for (unsigned i = 0; i < DCTSIZE2; ++i) {
40 void* userdata_reference = idct_reference_alloc(quant);
41 void* userdata = idct_alloc(quant);
43 for (unsigned i = 0; i < 1000; ++i) {
44 gen_random_coeffs(coeff, DCTSIZE2);
46 (*idct)(coeff, userdata, output);
47 (idct_reference)(coeff, userdata_reference, reference);
49 // Find the RMS difference.
51 for (unsigned i = 0; i < DCTSIZE2; ++i) {
52 diff_squared += (output[i] - reference[i]) * (output[i] - reference[i]);
55 assert(diff_squared <= 5);
58 idct_reference_free(userdata_reference);
62 // Test that a single DC coefficient becomes spread out to all blocks.
63 void test_dc_becomes_spread_out(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
65 int16_t coeff[DCTSIZE2] = { 0 };
66 uint32_t quant[DCTSIZE2];
67 uint8_t output[DCTSIZE2];
69 // Unit quantization (ie., no scaling).
70 for (unsigned i = 0; i < DCTSIZE2; ++i) {
74 void* userdata = idct_alloc(quant);
76 for (unsigned i = 0; i < 255*8; ++i) {
77 uint32_t reference_value = i / 8;
80 (*idct)(coeff, userdata, output);
82 for (unsigned i = 0; i < DCTSIZE2; ++i) {
83 assert(abs(output[i] - reference_value) <= 1);
90 double timediff(const struct timeval* a, const struct timeval* b)
92 return (double)(b->tv_sec - a->tv_sec) +
93 (double)(b->tv_usec - a->tv_usec) * 1e-6;
96 void test_performance(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
98 const unsigned num_runs = (idct == idct_reference) ? 5000 : 5000000;
100 int16_t coeff[DCTSIZE2];
101 uint32_t quant[DCTSIZE2];
102 uint8_t output[DCTSIZE2];
104 gen_random_coeffs(coeff, DCTSIZE2);
106 // Unit quantization (ie., no scaling).
107 for (unsigned i = 0; i < DCTSIZE2; ++i) {
111 void* userdata = idct_alloc(quant);
113 start_benchmark_timer();
115 for (unsigned i = 0; i < num_runs; ++i) {
116 (*idct)(coeff, userdata, output);
119 double diff = stop_benchmark_timer();
120 printf("%u runs in %.2f CPU seconds = %.2f IDCTs/sec\n",
121 num_runs, diff, num_runs / diff);
126 void test_all_idct(idct_alloc_t* idct_alloc, idct_free_t* idct_free, idct_func_t* idct)
128 printf(" test_dc_becomes_spread_out()\n");
129 test_dc_becomes_spread_out(idct_alloc, idct_free, idct);
131 printf(" test_random_inputs()\n");
132 test_random_inputs(idct_alloc, idct_free, idct);
134 printf(" performance test: ");
135 test_performance(idct_alloc, idct_free, idct);
140 printf("idct_reference:\n");
141 test_all_idct(idct_reference_alloc, idct_reference_free, idct_reference);
143 printf("idct_float:\n");
144 test_all_idct(idct_float_alloc, idct_float_free, idct_float);
146 printf("All tests pass.\n");