#include #include #include #include #include #include "convolve.h" // --------------------------------------------------------------------------- // Misc utils // --------------------------------------------------------------------------- /* Generate some random values for testing */ static unsigned long rand_state = 0; static void rand_reset(void) { rand_state = 0; } static unsigned long rand_int(void) { rand_state = (1103515245UL * rand_state + 12345UL) & 0x7fffffffUL; return rand_state; } static float rand_float(void) { union { uint32_t u; float f; } r; uint32_t u = rand_int(); int e = 112 + ((u ^ (u>>8)) & 15); r.u = u & 0x007fffffUL; // Mantissa r.u |= (u & 0x00800000UL) << 8; // Sign r.u |= (e & 0xffUL) << 23; // Exponent return r.f; } static void gen_floats(float *vect, int len) { int i; for (i = 0; i < len; i++) vect[i] = rand_float(); } /* Show float vector data cut and paste friendly */ static void dump_floats(float *vect, int len, char *name) { int i; printf("static const float %s[] = {\n\t", name); for(i = 0; i < len; i++) { char *end; if (i == len-1) end = "\n"; else if ((i&3) == 3) end = ",\n\t"; else end = ", "; printf("%14.7ef%s", vect[i], end); } printf("};\n"); } /* Compare float with tolerance of delta (absolute) and epsilon (relative) */ static int compare_floats(const float *v0, const float *v1, int len, float delta, float epsilon) { int i; for (i=0; ix, 0, tv->x_len * sizeof(float)); memset(tv->h, 0, tv->h_len * sizeof(float)); memset(tv->y, 0, tv->y_len * sizeof(float)); gen_floats(tv->x, tv->x_len); gen_floats(tv->h, tv->h_len); } /* Allocate test vectors */ static struct test_vec * test_vec_alloc(int x_len, int h_len) { struct test_vec *tv; tv = calloc(1, sizeof(struct test_vec)); if (!tv) return NULL; tv->x_len = x_len; tv->h_len = h_len; tv->y_len = x_len; /* Results can never be longer than x */ tv->x = convolve_h_alloc(x_len); tv->h = convolve_h_alloc(h_len); tv->y = convolve_h_alloc(tv->y_len); test_vec_reset(tv, 0); return tv; } /* Release test vectors */ static void test_vec_release(struct test_vec *tv) { if (!tv) return; free(tv->x); free(tv->h); free(tv->y); free(tv); } /* Run convolution */ static int run_convolve(struct test_vec *tv, int h_len, enum test_type type) { int x_len; int start, len; test_vec_reset(tv, 0); /* Compute params that fit within our test vectors */ x_len = tv->x_len / 2; /* float vs complex */ start = h_len - 1; len = x_len - start; /* Run implementation */ switch (type) { case CONV_REAL_BASE: base_convolve_real( tv->x, x_len, tv->h, h_len, tv->y, tv->y_len, start, len ); break; case CONV_REAL_OPT: convolve_real( tv->x, x_len, tv->h, h_len, tv->y, tv->y_len, start, len ); break; case CONV_COMPLEX_BASE: base_convolve_complex( tv->x, x_len, tv->h, h_len, tv->y, tv->y_len, start, len ); break; case CONV_COMPLEX_OPT: convolve_complex( tv->x, x_len, tv->h, h_len, tv->y, tv->y_len, start, len ); break; } return len * 2; } int main(int argc, char *argv[]) { struct test_vec *tv; int gen_ref_mode = 0; char name[80]; int i, j, len; convolve_init(); /* Mode */ gen_ref_mode = (argc == 2) && !strcmp("genref", argv[1]); /* Alloc test vectors */ /* All *2 is to account for the facts all vectors are actually * complex and need two floats */ tv = test_vec_alloc(100*2, 25*2); /* Dump all input data to make sure we work off the same input data */ if (!gen_ref_mode) { printf("==== TEST INPUT DATA ====\n"); dump_floats(tv->x, tv->x_len, "x"); dump_floats(tv->h, tv->h_len, "h"); printf("\n"); printf("\n"); } /* Run through all the tests */ if (!gen_ref_mode) printf("==== TEST ====\n"); for (i=0; tests[i].h_len; i++) { for (j=0; j<(gen_ref_mode ? 1 : 2); j++) { len = run_convolve(tv, tests[i].h_len, tests[i].type + j); snprintf(name, sizeof(name)-1, "y_ref_%s_%d", type_name[tests[i].type + j], tests[i].h_len); if (gen_ref_mode) { /* If in generate mode, output data */ dump_floats(tv->y, len, name); } else { /* If in test mode, compare with data */ printf("%s: %s\n", name, compare_floats(tests[i].y_ref, tv->y, len, 1e-5f, 1e-5f) ? "FAIL" : "PASS" ); } } } if (!gen_ref_mode) { printf("\n"); printf("\n"); } /* All done ! */ test_vec_release(tv); return 0; }