11 // Generate random coefficients in the range [-15..15].
12 void gen_random_coeffs(int16_t* dst, size_t len)
14 // Standard NR LCG (we avoid rand() to get consistent behavior across platforms).
15 static uint32_t seed = 1234;
16 for (unsigned i = 0; i < len; ++i) {
17 seed = seed * 1664525U + 1013904223U;
19 dst[i] = (uint8_t)(seed >> 27) & 0x7;
21 dst[i] = -((uint8_t)(seed >> 27) & 0x7);
26 // Test that the input is pretty close to the reference for random inputs.
27 // (If the reference funtion is given in, this becomes a simple test of its
29 void test_random_inputs(idct_func_t* idct)
31 int16_t coeff[DCTSIZE2];
32 uint32_t quant[DCTSIZE2];
33 uint8_t output[DCTSIZE2];
34 uint8_t reference[DCTSIZE2];
36 // Unit quantization (ie., no scaling).
37 for (unsigned i = 0; i < DCTSIZE2; ++i) {
41 for (unsigned i = 0; i < 1000; ++i) {
42 gen_random_coeffs(coeff, DCTSIZE2);
44 (*idct)(coeff, quant, output);
45 (idct_reference)(coeff, quant, reference);
47 // Find the RMS difference.
49 for (unsigned i = 0; i < DCTSIZE2; ++i) {
50 diff_squared += (output[i] - reference[i]) * (output[i] - reference[i]);
53 assert(diff_squared <= 5);
57 // Test that a single DC coefficient becomes spread out to all blocks.
58 void test_dc_becomes_spread_out(idct_func_t* idct)
60 int16_t coeff[DCTSIZE2] = { 0 };
61 uint32_t quant[DCTSIZE2];
62 uint8_t output[DCTSIZE2];
64 // Unit quantization (ie., no scaling).
65 for (unsigned i = 0; i < DCTSIZE2; ++i) {
69 for (unsigned i = 0; i < 255*8; ++i) {
70 uint32_t reference_value = i / 8;
73 (*idct)(coeff, quant, output);
75 for (unsigned i = 0; i < DCTSIZE2; ++i) {
76 assert(abs(output[i] - reference_value) <= 1);
81 double timediff(const struct timeval* a, const struct timeval* b)
83 return (double)(b->tv_sec - a->tv_sec) +
84 (double)(b->tv_usec - a->tv_usec) * 1e-6;
87 void test_performance(idct_func_t* idct)
89 const unsigned num_runs = (idct == idct_reference) ? 5000 : 5000000;
91 int16_t coeff[DCTSIZE2];
92 uint32_t quant[DCTSIZE2];
93 uint8_t output[DCTSIZE2];
95 gen_random_coeffs(coeff, DCTSIZE2);
97 // Unit quantization (ie., no scaling).
98 for (unsigned i = 0; i < DCTSIZE2; ++i) {
102 struct timeval start, now;
103 gettimeofday(&start, NULL);
105 for (unsigned i = 0; i < num_runs; ++i) {
106 (*idct)(coeff, quant, output);
109 gettimeofday(&now, NULL);
111 double diff = timediff(&start, &now);
112 printf("%u runs in %.2f seconds = %.2f DCTs/sec\n",
113 num_runs, diff, num_runs / diff);
116 void test_all_idct(idct_func_t* idct)
118 printf(" test_dc_becomes_spread_out()\n");
119 test_dc_becomes_spread_out(idct);
121 printf(" test_random_inputs()\n");
122 test_random_inputs(idct);
124 printf(" performance test: ");
125 test_performance(idct);
130 printf("idct_reference:\n");
131 test_all_idct(idct_reference);
133 printf("idct_float:\n");
134 test_all_idct(idct_float);
136 printf("All tests pass.\n");