view test/test_arith.h @ 23:e26874655738

*: huge refactor, new major release (hahaha) I keep finding things that are broken... The problem NOW was that vec would unintentionally build some functions with extended instruction sets, which is Bad and would mean that for all intents and purposes the CPU detection was completely broken. Now vec is no longer header only either. Boohoo. However this gives a lot more flexibility to vec since we no longer want or need to care about C++ crap. The NEON and Altivec implementations have not been updated which means they won't compile hence why they're commented out in the cmake build file.
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 02:52:40 -0500
parents 41dd962abdd1
children 92156fe32755
line wrap: on
line source

#define CREATE_TEST(sign, psign, csign, bits, size, op, equiv) \
	static int test_arith_v##sign##int##bits##x##size##_##op(v##sign##int##bits##x##size a, v##sign##int##bits##x##size b) \
	{ \
		V##csign##INT##bits##x##size##_ALIGNED_ARRAY(orig_a); \
		V##csign##INT##bits##x##size##_ALIGNED_ARRAY(orig_b); \
		V##csign##INT##bits##x##size##_ALIGNED_ARRAY(orig_c); \
	\
		v##sign##int##bits##x##size c = v##sign##int##bits##x##size##_##op(a, b); \
	\
		v##sign##int##bits##x##size##_store_aligned(a, orig_a); \
		v##sign##int##bits##x##size##_store_aligned(b, orig_b); \
		v##sign##int##bits##x##size##_store_aligned(c, orig_c); \
	\
		for (int i = 0; i < size; i++) { \
			if ((sign##int##bits##_t)(equiv) != orig_c[i]) { \
				fprintf(stderr, "v" #sign "int" #bits "x" #size "_" #op " test FAILED at index %d: (" #equiv ") [%" PRI ## psign ## bits "] does not equal result [%" PRI ## psign ## bits "]!\n", i, equiv, orig_c[i]); \
				print_v##sign##int##bits##x##size(stderr,a); \
				print_v##sign##int##bits##x##size(stderr,b); \
				print_v##sign##int##bits##x##size(stderr,c); \
				fprintf(stderr, "\n"); \
				return 1; \
			} \
		} \
	\
		return 0; \
	}

#define CREATE_TEST_SHIFT(sign, psign, csign, bits, size, op, equiv) \
	static int test_arith_v##sign##int##bits##x##size##_##op(v##sign##int##bits##x##size a, vuint##bits##x##size b) \
	{ \
		V##csign##INT##bits##x##size##_ALIGNED_ARRAY(orig_a); \
		VUINT##bits##x##size##_ALIGNED_ARRAY(orig_b); \
		V##csign##INT##bits##x##size##_ALIGNED_ARRAY(orig_c); \
	\
		v##sign##int##bits##x##size c = v##sign##int##bits##x##size##_##op(a, b); \
	\
		v##sign##int##bits##x##size##_store_aligned(a, orig_a); \
		vuint##bits##x##size##_store_aligned(b, orig_b); \
		v##sign##int##bits##x##size##_store_aligned(c, orig_c); \
	\
		for (int i = 0; i < size; i++) { \
			if ((vec_##sign##int##bits)(equiv) != orig_c[i]) { \
				fprintf(stderr, "v" #sign "int" #bits "x" #size "_" #op " test FAILED at index %d: (" #equiv ") [%" PRI ## psign ## bits "] does not equal result [%" PRI ## psign ## bits "]!\n", i, (vec_##sign##int##bits)(equiv), orig_c[i]); \
				print_v##sign##int##bits##x##size(stderr,a); \
				print_vuint##bits##x##size(stderr,b); \
				print_v##sign##int##bits##x##size(stderr,c); \
				fprintf(stderr, "\n"); \
				return 1; \
			} \
		} \
	\
		return 0; \
	}

#define CREATE_TESTS_SIGN(sign, psign, csign, bits, size) \
	CREATE_TEST(sign, psign, csign, bits, size, add, orig_a[i] + orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, sub, orig_a[i] - orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, mul, orig_a[i] * orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, div, (orig_b[i]) ? (orig_a[i] / orig_b[i]) : 0) \
	CREATE_TEST(sign, psign, csign, bits, size, and, orig_a[i] & orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, or,  orig_a[i] | orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, xor, orig_a[i] ^ orig_b[i]) \
	CREATE_TEST(sign, psign, csign, bits, size, avg, (orig_a[i] + orig_b[i] + 1) / 2) \
	CREATE_TEST_SHIFT(sign, psign, csign, bits, size, rshift, vec_##sign##rshift(orig_a[i], orig_b[i])) \
	CREATE_TEST_SHIFT(sign, psign, csign, bits, size, lshift, vec_##sign##lshift(orig_a[i], orig_b[i])) \
	CREATE_TEST_SHIFT(sign, psign, csign, bits, size, lrshift, vec_lrshift((vec_uint##bits)orig_a[i], orig_b[i]))

#define CREATE_TESTS(bits, size) \
	CREATE_TESTS_SIGN(, d, , bits, size) \
	CREATE_TESTS_SIGN(u, u, U, bits, size)

CREATE_TESTS(8, 2)

CREATE_TESTS(8, 4)
CREATE_TESTS(16, 2)

CREATE_TESTS(8, 8)
CREATE_TESTS(16, 4)
CREATE_TESTS(32, 2)

CREATE_TESTS(8, 16)
CREATE_TESTS(16, 8)
CREATE_TESTS(32, 4)
CREATE_TESTS(64, 2)

CREATE_TESTS(8, 32)
CREATE_TESTS(16, 16)
CREATE_TESTS(32, 8)
CREATE_TESTS(64, 4)

CREATE_TESTS(8, 64)
CREATE_TESTS(16, 32)
CREATE_TESTS(32, 16)
CREATE_TESTS(64, 8)

#undef CREATE_TESTS_SIGN
#undef CREATE_TESTS
#undef CREATE_TEST
#undef CREATE_TEST_SHIFT

static int test_arith(void)
{
	int ret = 0;

#define RUN_TESTS_SIGN(sign, bits, size) \
	for (size_t i = 0U; i < ARRAY_SIZE(testval##sign##bits); i++) { \
		const v##sign##int##bits##x##size a = vtest##sign##bits##x##size(i); \
		for (size_t j = 0U; j < ARRAY_SIZE(testval##sign##bits); j++) { \
			const v##sign##int##bits##x##size b = vtest##sign##bits##x##size(j); \
			ret |= test_arith_v##sign##int##bits##x##size##_add(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_sub(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_mul(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_div(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_and(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_or(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_xor(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_avg(a, b); \
		} \
	} \
	\
	for (size_t i = 0U; i < ARRAY_SIZE(testval##sign##bits); i++) { \
		const v##sign##int##bits##x##size a = vtest##sign##bits##x##size(i); \
		for (uint32_t j = 0U; j < bits; j++) { \
			const vuint##bits##x##size b = vuint##bits##x##size##_splat(j); \
			ret |= test_arith_v##sign##int##bits##x##size##_rshift(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_lshift(a, b); \
			ret |= test_arith_v##sign##int##bits##x##size##_lrshift(a, b); \
		} \
	}

#define RUN_TESTS(bits, size) \
	RUN_TESTS_SIGN( , bits, size) \
	RUN_TESTS_SIGN(u, bits, size)

	RUN_TESTS(8, 2)

	RUN_TESTS(8, 4)
	RUN_TESTS(16, 2)

	RUN_TESTS(8, 8)
	RUN_TESTS(16, 4)
	RUN_TESTS(32, 2)

	RUN_TESTS(8, 16)
	RUN_TESTS(16, 8)
	RUN_TESTS(32, 4)
	RUN_TESTS(64, 2)

	RUN_TESTS(8, 32)
	RUN_TESTS(16, 16)
	RUN_TESTS(32, 8)
	RUN_TESTS(64, 4)

	RUN_TESTS(8, 64)
	RUN_TESTS(16, 32)
	RUN_TESTS(32, 16)
	RUN_TESTS(64, 8)

#undef RUN_TESTS_SIGN
#undef RUN_TESTS

	return ret;
}