view test/test_arith.h @ 25:92156fe32755

impl/ppc/altivec: update to new implementation the signed average function is wrong; it needs to round up the number when only one of them is odd, but that doesn't necessarily seem to be true because altivec is weird, and that's what we need to emulate the quirks for. ugh. also the altivec backend uses the generic functions instead of fallbacks because it does indeed use the exact same memory structure as the generic implementation...
author Paper <paper@tflc.us>
date Sun, 24 Nov 2024 11:15:59 +0000
parents e26874655738
children
line wrap: on
line source

#include <math.h>

#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, (sign##int##bits##_t)(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, vec_##sign##avg(orig_a[i], orig_b[i])) \
	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;
}