changeset 34:8b5e0974fd41

Backed out changeset 92156fe32755
author Paper <paper@tflc.us>
date Fri, 25 Apr 2025 17:40:46 -0400
parents 4655b49eaf9f
children 99e4539f922f
files CMakeLists.txt include/vec/vec.h src/cpu.c src/impl/fallback.c src/impl/generic.c src/impl/ppc/altivec.c src/vec.c test/CMakeLists.txt test/test_arith.h
diffstat 9 files changed, 74 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Apr 25 17:40:42 2025 -0400
+++ b/CMakeLists.txt	Fri Apr 25 17:40:46 2025 -0400
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.23)
 
-project(vec VERSION 3.0.0 DESCRIPTION "a tiny C99 SIMD vector library" LANGUAGES C)
+project(vec VERSION 3.0.0 DESCRIPTION "a tiny C99 SIMD vector library")
 
 add_library(vec SHARED "src/vec.c;src/cpu.c;src/impl/generic.c;src/impl/fallback.c")
 
@@ -33,10 +33,10 @@
 	endif()
 	# TODO we have to try_compile to detect NEON
 else()
-	check_c_compiler_flag("-maltivec" COMPILER_HAS_ALTIVEC)
-	if(COMPILER_HAS_ALTIVEC)
-		set(COMPILER_ALTIVEC_FLAGS "-maltivec")
-	endif()
+	#check_c_compiler_flag("-maltivec" COMPILER_HAS_ALTIVEC)
+	#if(COMPILER_HAS_ALTIVEC)
+	#	set(COMPILER_ALTIVEC_FLAGS "-maltivec")
+	#endif()
 	#check_c_compiler_flag("-mfpu=neon" COMPILER_HAS_NEON)
 	#if(COMPILER_HAS_NEON)
 	#	set(COMPILER_NEON_FLAGS "-mfpu=neon")
--- a/include/vec/vec.h	Fri Apr 25 17:40:42 2025 -0400
+++ b/include/vec/vec.h	Fri Apr 25 17:40:46 2025 -0400
@@ -237,28 +237,6 @@
 	return xx.d;
 }
 
-inline vec_intmax vec_avg(vec_intmax x, vec_intmax y)
-{
-    if ((x < 0) == (y < 0)) { // same sign
-        // this gets the equivalent of:
-        // vec_int32 r = ((vec_int64)x + (vec_int64)y) / 2;
-        vec_intmax r = (x / 2) + (y / 2) + (((x % 2) + (y % 2)) / 2);
-
-        // FIXME emulate AltiVec quirks
-
-        return r;
-    } else {
-        vec_intmax r = (x + y) / 2;
-        // FIXME emulate AltiVec quirks
-        return r;
-    }
-}
-
-inline vec_uintmax vec_uavg(vec_uintmax x, vec_uintmax y)
-{
-    return (x / 2) + (y / 2) + ((x | y) & 1);
-}
-
 //////////////////////////////////////////////////////////////////////////////
 // array alignment
 
--- a/src/cpu.c	Fri Apr 25 17:40:42 2025 -0400
+++ b/src/cpu.c	Fri Apr 25 17:40:46 2025 -0400
@@ -44,7 +44,6 @@
  * 3. This notice may not be removed or altered from any source distribution.
 */
 
-#include "vec/vec.h"
 #include "vec/cpu.h"
 
 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
@@ -56,7 +55,7 @@
 #elif defined(__FreeBSD__) && defined(__powerpc__)
 # include <machine/cpu.h>
 # include <sys/auxv.h>
-#elif defined(VEC_COMPILER_HAS_ALTIVEC)
+#elif defined(__ALTIVEC__)
 # include <signal.h>
 # include <setjmp.h>
 #endif
@@ -311,8 +310,8 @@
 	void (*handler)(int sig);
 	handler = signal(SIGILL, vec_CPU_illegal_instruction);
 	if (!setjmp(vec_jmpbuf)) {
-		__asm__ __volatile__("mtspr 256, %0\n\t"
-		    "vand %%v0, %%v0, %%v0" ::"r"(-1));
+		vector unsigned char vec;
+		vec_and(vec, vec);
 		altivec = 1;
 	}
 	signal(SIGILL, handler);
@@ -495,4 +494,4 @@
 			vec_CPU_features |= VEC_CPU_HAS_NEON;
 	}
 	return vec_CPU_features;
-}
+}
\ No newline at end of file
--- a/src/impl/fallback.c	Fri Apr 25 17:40:42 2025 -0400
+++ b/src/impl/fallback.c	Fri Apr 25 17:40:46 2025 -0400
@@ -83,7 +83,7 @@
 	\
 	v##sign##int##bits##x##size v##sign##int##bits##x##size##_fallback_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		VEC_FALLBACK_OPERATION(vec_##sign##avg(varr1[i], varr2[i]), sign, csign, bits, size); \
+		VEC_FALLBACK_OPERATION((varr1[i] + varr2[i] + 1) / 2, sign, csign, bits, size); \
 	} \
 	\
 	v##sign##int##bits##x##size v##sign##int##bits##x##size##_fallback_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
--- a/src/impl/generic.c	Fri Apr 25 17:40:42 2025 -0400
+++ b/src/impl/generic.c	Fri Apr 25 17:40:46 2025 -0400
@@ -68,13 +68,7 @@
 	\
 	v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-	    union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-	    union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		for (int i = 0; i < size; i++) \
-			vec1d->impl[i] = vec_##sign##avg(vec1d->impl[i], vec2d->impl[i]); \
-	\
-		return vec1d->vec; \
+		VEC_GENERIC_OPERATION((((union v##sign##int##bits##x##size##_impl_data *)&vec1)->impl[i] + ((union v##sign##int##bits##x##size##_impl_data *)&vec2)->impl[i] + 1) / 2, sign, csign, bits, size); \
 	} \
 	\
 	v##sign##int##bits##x##size v##sign##int##bits##x##size##_generic_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
--- a/src/impl/ppc/altivec.c	Fri Apr 25 17:40:42 2025 -0400
+++ b/src/impl/ppc/altivec.c	Fri Apr 25 17:40:46 2025 -0400
@@ -23,61 +23,38 @@
 **/
 
 #include "vec/impl/ppc/altivec.h"
-#include "vec/impl/generic.h"
 
 #include <altivec.h>
 
-#define VEC_DEFINE_IMPL_DATA(sign, bits, size, type) \
-    union v##sign##int##bits##x##size##_impl_data { \
-	    v##sign##int##bits##x##size vec; \
-	    vector type altivec; \
-    }; \
-    \
-	VEC_STATIC_ASSERT(VEC_ALIGNOF(vector type) <= VEC_ALIGNOF(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " alignment needs to be expanded to fit intrinsic type size"); \
-	VEC_STATIC_ASSERT(sizeof(vector type) <= sizeof(v##sign##int##bits##x##size), "vec: v" #sign "int" #bits "x" #size " needs to be expanded to fit intrinsic type size");
-
-VEC_DEFINE_IMPL_DATA( , 8,  16, signed char)
-VEC_DEFINE_IMPL_DATA(u, 8,  16, unsigned char)
-VEC_DEFINE_IMPL_DATA( , 16, 8,  signed short)
-VEC_DEFINE_IMPL_DATA(u, 16, 8,  unsigned short)
-VEC_DEFINE_IMPL_DATA( , 32, 4,  signed int)
-VEC_DEFINE_IMPL_DATA(u, 32, 4,  unsigned int)
-
-#undef VEC_DEFINE_IMPL_DATA
-
 /* GCC 4.2.1 on Mac OS X doesn't have these for some reason */
 #ifdef vec_mul
 # define VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_mul(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_mul(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_mul(vec1.altivec, vec2.altivec); \
+		return vec; \
 	}
 # define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_mul
 #else
 # define VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size)
-# define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) \
-    v##sign##int##bits##x##size##_generic_mul
+# define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) NULL
 #endif
 
 #ifdef vec_splats
 # define VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_splat(vec_##sign##int##bits x) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data vec; \
+		v##sign##int##bits##x##size vec; \
 		vec.altivec = vec_splats(x); \
-		return vec.vec; \
+		return vec; \
 	}
 # define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_splat
 #else
 # define VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size)
-# define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) \
-    v##sign##int##bits##x##size##_generic_splat
+# define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) NULL
 #endif
 
 #define VEC_ALTIVEC_uRSHIFT vec_sr
@@ -86,18 +63,15 @@
 #define VEC_ALTIVEC_DEFINE_uLRSHIFT(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_lrshift(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_sr(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_sr(vec1.altivec, vec2.altivec); \
+		return vec; \
 	}
 #define VEC_ALTIVEC_STRUCT_uLRSHIFT(sign, csign, bits, size) \
 	v##sign##int##bits##x##size##_altivec_lrshift
 
 #define VEC_ALTIVEC_DEFINE_LRSHIFT(sign, csign, bits, size)
-#define VEC_ALTIVEC_STRUCT_LRSHIFT(sign, csign, bits, size) \
-    v##sign##int##bits##x##size##_generic_lrshift
+#define VEC_ALTIVEC_STRUCT_LRSHIFT(sign, csign, bits, size) NULL
 
 #define VEC_ALTIVEC_CAST_BOOL_8 (vector signed char)
 #define VEC_ALTIVEC_CAST_BOOL_U8 (vector unsigned char)
@@ -111,161 +85,135 @@
 #define VEC_DEFINE_OPERATIONS_SIGN(sign, csign, bits, size) \
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_load_aligned(const vec_##sign##int##bits in[size]) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data vec; \
+		v##sign##int##bits##x##size vec; \
 		vec.altivec = vec_ld(0, in); \
-		return vec.vec; \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_load(const vec_##sign##int##bits in[size]) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data vec; \
+		v##sign##int##bits##x##size vec; \
 		vec.altivec = vec_perm(vec_ld(0, in), vec_ld(15, in), vec_lvsl(0, in)); \
-		return vec.vec; \
+		return vec; \
 	} \
 	\
 	static void v##sign##int##bits##x##size##_altivec_store_aligned(v##sign##int##bits##x##size vec, vec_##sign##int##bits out[size]) \
 	{ \
-		vec_st(((union v##sign##int##bits##x##size##_impl_data *)&vec)->altivec, 0, out); \
+		vec_st(vec.altivec, 0, out); \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_add(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_add(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_add(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_sub(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_sub(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_sub(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_MUL(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_lshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_sl(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_sl(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_rshift(v##sign##int##bits##x##size vec1, vuint##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union vuint##bits##x##size##_impl_data *vec2d = (union vuint##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_##sign##RSHIFT(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_##sign##RSHIFT(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_##sign##LRSHIFT(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_avg(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_avg(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_avg(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_and(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_and(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_and(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_or(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_or(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_or(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_xor(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = vec_xor(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = vec_xor(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	VEC_ALTIVEC_DEFINE_SPLAT(sign, csign, bits, size) \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmplt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits  vec_cmplt(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits  vec_cmplt(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmple(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmplt(vec1d->altivec, vec2d->altivec), vec_cmpeq(vec1d->altivec, vec2d->altivec)); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmplt(vec1.altivec, vec2.altivec), vec_cmpeq(vec1.altivec, vec2.altivec)); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpeq(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpeq(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpeq(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpge(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmpgt(vec1d->altivec, vec2d->altivec), vec_cmpeq(vec1d->altivec, vec2d->altivec)); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_or(vec_cmpgt(vec1.altivec, vec2.altivec), vec_cmpeq(vec1.altivec, vec2.altivec)); \
+		return vec; \
 	} \
 	\
 	static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_cmpgt(v##sign##int##bits##x##size vec1, v##sign##int##bits##x##size vec2) \
 	{ \
-		union v##sign##int##bits##x##size##_impl_data *vec1d = (union v##sign##int##bits##x##size##_impl_data *)&vec1; \
-		union v##sign##int##bits##x##size##_impl_data *vec2d = (union v##sign##int##bits##x##size##_impl_data *)&vec2; \
-	\
-		vec1d->altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpgt(vec1d->altivec, vec2d->altivec); \
-		return vec1d->vec; \
+		v##sign##int##bits##x##size vec; \
+		vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpgt(vec1.altivec, vec2.altivec); \
+		return vec; \
 	} \
 	\
-	const v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_altivec = { \
+	static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_altivec = { \
 		VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size), \
 		v##sign##int##bits##x##size##_altivec_load_aligned, \
 		v##sign##int##bits##x##size##_altivec_load, \
 		v##sign##int##bits##x##size##_altivec_store_aligned, \
-		v##sign##int##bits##x##size##_generic_store, \
+		/* .store = */ NULL, \
 		v##sign##int##bits##x##size##_altivec_add, \
 		v##sign##int##bits##x##size##_altivec_sub, \
 		VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size), \
-		v##sign##int##bits##x##size##_generic_div, \
+		/* .div = */ NULL, \
 		v##sign##int##bits##x##size##_altivec_avg, \
 		v##sign##int##bits##x##size##_altivec_and, \
 		v##sign##int##bits##x##size##_altivec_or, \
 		v##sign##int##bits##x##size##_altivec_xor, \
-		v##sign##int##bits##x##size##_generic_not, \
+		/* .not = */ NULL, \
 		v##sign##int##bits##x##size##_altivec_lshift, \
 		v##sign##int##bits##x##size##_altivec_rshift, \
 		VEC_ALTIVEC_STRUCT_##sign##LRSHIFT(sign, csign, bits, size), \
--- a/src/vec.c	Fri Apr 25 17:40:42 2025 -0400
+++ b/src/vec.c	Fri Apr 25 17:40:46 2025 -0400
@@ -55,9 +55,6 @@
 extern inline vec_intmax vec_rshift(vec_intmax x, unsigned int y);
 extern inline vec_intmax vec_lshift(vec_intmax x, unsigned int y);
 
-extern inline vec_intmax vec_avg(vec_intmax x, vec_intmax y);
-extern inline vec_uintmax vec_uavg(vec_uintmax x, vec_uintmax y);
-
 // 16-bit
 const vint8x2_impl   *vint8x2_impl_cpu   = &vint8x2_impl_generic;
 const vuint8x2_impl  *vuint8x2_impl_cpu  = &vuint8x2_impl_generic;
--- a/test/CMakeLists.txt	Fri Apr 25 17:40:42 2025 -0400
+++ b/test/CMakeLists.txt	Fri Apr 25 17:40:46 2025 -0400
@@ -1,10 +1,10 @@
 cmake_minimum_required(VERSION 3.23)
 
-project(vec-tests LANGUAGES C)
+project(vec-tests)
 
 # add main vec directory
 add_subdirectory(.. vec)
 
 add_executable(vec-tests test.c)
 
-target_link_libraries(vec-tests vec m)
+target_link_libraries(vec-tests vec)
--- a/test/test_arith.h	Fri Apr 25 17:40:42 2025 -0400
+++ b/test/test_arith.h	Fri Apr 25 17:40:46 2025 -0400
@@ -1,5 +1,3 @@
-#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) \
 	{ \
@@ -15,7 +13,7 @@
 	\
 		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]); \
+				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); \
@@ -62,7 +60,7 @@
 	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(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]))