Some asm() correction.
[fjl] / idct_test.c
index b4cec38..bd39c74 100644 (file)
@@ -3,10 +3,12 @@
 #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)
@@ -26,23 +28,26 @@ 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;
@@ -52,30 +57,42 @@ void test_random_inputs(idct_func_t* idct)
 
                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)
@@ -84,7 +101,7 @@ 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;
 
@@ -99,36 +116,43 @@ void test_performance(idct_func_t* idct)
                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;