#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#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; i<len; i++)
	{
		float a = v0[i];
		float b = v1[i];

		if (fabsf(a - b) < delta)
			continue;

		if (fabsf(1.0f - (a/b)) < epsilon)
			continue;

		return 1;
	}

	return 0;
}


// ---------------------------------------------------------------------------
// Golden reference results
// ---------------------------------------------------------------------------

#include "convolve_test_golden.h"

enum test_type {
	CONV_REAL_BASE		= 0,
	CONV_REAL_OPT		= 1,
	CONV_COMPLEX_BASE	= 2,
	CONV_COMPLEX_OPT	= 3
};

struct test_data {
	enum test_type type;
	int h_len;
	const  float *y_ref;
};

static const char *type_name[] = {
	"real_base", "real_opt", "complex_base", "complex_opt",
};

static const struct test_data tests[] = {
	{ CONV_REAL_BASE,  4, y_ref_real_base_4 },
	{ CONV_REAL_BASE,  8, y_ref_real_base_8 },
	{ CONV_REAL_BASE, 12, y_ref_real_base_12 },
	{ CONV_REAL_BASE, 16, y_ref_real_base_16 },
	{ CONV_REAL_BASE, 20, y_ref_real_base_20 },
	{ CONV_REAL_BASE, 24, y_ref_real_base_24 },
	{ CONV_COMPLEX_BASE,  4, y_ref_complex_base_4 },
	{ CONV_COMPLEX_BASE,  8, y_ref_complex_base_8 },
	{ CONV_COMPLEX_BASE, 12, y_ref_complex_base_12 },
	{ CONV_COMPLEX_BASE, 16, y_ref_complex_base_16 },
	{ CONV_COMPLEX_BASE, 20, y_ref_complex_base_20 },
	{ CONV_COMPLEX_BASE, 24, y_ref_complex_base_24 },
	{ 0, 0, NULL },
};


// ---------------------------------------------------------------------------
// Main testing logic
// ---------------------------------------------------------------------------

struct test_vec
{
	float *x;
	float *h;
	float *y;

	int x_len;	/* These are in # of _floats_ ! */
	int h_len;	/* These are in # of _floats_ ! */
	int y_len;	/* These are in # of _floats_ ! */
};

/* Reset test vectors */
static void
test_vec_reset(struct test_vec *tv, int seed)
{
	rand_reset();

	memset(tv->x, 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;
}
