Mercurial > vec
changeset 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 | e49e70f7012f |
children | 6c91cd9a2f2d |
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, 160 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Sun Nov 24 03:32:53 2024 -0500 +++ b/CMakeLists.txt Sun Nov 24 11:15:59 2024 +0000 @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.23) -project(vec VERSION 3.0.0 DESCRIPTION "a tiny C99 SIMD vector library") +project(vec VERSION 3.0.0 DESCRIPTION "a tiny C99 SIMD vector library" LANGUAGES C) 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/include/vec/vec.h Sun Nov 24 11:15:59 2024 +0000 @@ -237,6 +237,28 @@ 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/src/cpu.c Sun Nov 24 11:15:59 2024 +0000 @@ -44,6 +44,7 @@ * 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__)) @@ -55,7 +56,7 @@ #elif defined(__FreeBSD__) && defined(__powerpc__) # include <machine/cpu.h> # include <sys/auxv.h> -#elif defined(__ALTIVEC__) +#elif defined(VEC_COMPILER_HAS_ALTIVEC) # include <signal.h> # include <setjmp.h> #endif @@ -310,8 +311,8 @@ void (*handler)(int sig); handler = signal(SIGILL, vec_CPU_illegal_instruction); if (!setjmp(vec_jmpbuf)) { - vector unsigned char vec; - vec_and(vec, vec); + __asm__ __volatile__("mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" ::"r"(-1)); altivec = 1; } signal(SIGILL, handler); @@ -494,4 +495,4 @@ vec_CPU_features |= VEC_CPU_HAS_NEON; } return vec_CPU_features; -} \ No newline at end of file +}
--- a/src/impl/fallback.c Sun Nov 24 03:32:53 2024 -0500 +++ b/src/impl/fallback.c Sun Nov 24 11:15:59 2024 +0000 @@ -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((varr1[i] + varr2[i] + 1) / 2, sign, csign, bits, size); \ + VEC_FALLBACK_OPERATION(vec_##sign##avg(varr1[i], varr2[i]), 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/src/impl/generic.c Sun Nov 24 11:15:59 2024 +0000 @@ -68,7 +68,13 @@ \ 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) \ { \ - 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); \ + 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; \ } \ \ 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/src/impl/ppc/altivec.c Sun Nov 24 11:15:59 2024 +0000 @@ -23,38 +23,61 @@ **/ #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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_mul(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } # 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) NULL +# define VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size) \ + v##sign##int##bits##x##size##_generic_mul #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) \ { \ - v##sign##int##bits##x##size vec; \ + union v##sign##int##bits##x##size##_impl_data vec; \ vec.altivec = vec_splats(x); \ - return vec; \ + return vec.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) NULL +# define VEC_ALTIVEC_STRUCT_SPLAT(sign, csign, bits, size) \ + v##sign##int##bits##x##size##_generic_splat #endif #define VEC_ALTIVEC_uRSHIFT vec_sr @@ -63,15 +86,18 @@ #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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_sr(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } #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) NULL +#define VEC_ALTIVEC_STRUCT_LRSHIFT(sign, csign, bits, size) \ + v##sign##int##bits##x##size##_generic_lrshift #define VEC_ALTIVEC_CAST_BOOL_8 (vector signed char) #define VEC_ALTIVEC_CAST_BOOL_U8 (vector unsigned char) @@ -85,135 +111,161 @@ #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]) \ { \ - v##sign##int##bits##x##size vec; \ + union v##sign##int##bits##x##size##_impl_data vec; \ vec.altivec = vec_ld(0, in); \ - return vec; \ + return vec.vec; \ } \ \ static v##sign##int##bits##x##size v##sign##int##bits##x##size##_altivec_load(const vec_##sign##int##bits in[size]) \ { \ - v##sign##int##bits##x##size vec; \ + union v##sign##int##bits##x##size##_impl_data vec; \ vec.altivec = vec_perm(vec_ld(0, in), vec_ld(15, in), vec_lvsl(0, in)); \ - return vec; \ + return vec.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(vec.altivec, 0, out); \ + vec_st(((union v##sign##int##bits##x##size##_impl_data *)&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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_add(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_sub(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_sl(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = VEC_ALTIVEC_##sign##RSHIFT(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_avg(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_and(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_or(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = vec_xor(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmplt(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - 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; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpeq(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ 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) \ { \ - 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; \ + 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; \ } \ \ 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) \ { \ - v##sign##int##bits##x##size vec; \ - vec.altivec = VEC_ALTIVEC_CAST_BOOL_##csign##bits vec_cmpgt(vec1.altivec, vec2.altivec); \ - return vec; \ + 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; \ } \ \ - static v##sign##int##bits##x##size##_impl v##sign##int##bits##x##size##_impl_altivec = { \ + const 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, \ - /* .store = */ NULL, \ + v##sign##int##bits##x##size##_generic_store, \ v##sign##int##bits##x##size##_altivec_add, \ v##sign##int##bits##x##size##_altivec_sub, \ VEC_ALTIVEC_STRUCT_MUL(sign, csign, bits, size), \ - /* .div = */ NULL, \ + v##sign##int##bits##x##size##_generic_div, \ 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, \ - /* .not = */ NULL, \ + v##sign##int##bits##x##size##_generic_not, \ 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/src/vec.c Sun Nov 24 11:15:59 2024 +0000 @@ -55,6 +55,9 @@ 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 Sun Nov 24 03:32:53 2024 -0500 +++ b/test/CMakeLists.txt Sun Nov 24 11:15:59 2024 +0000 @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.23) -project(vec-tests) +project(vec-tests LANGUAGES C) # add main vec directory add_subdirectory(.. vec) add_executable(vec-tests test.c) -target_link_libraries(vec-tests vec) +target_link_libraries(vec-tests vec m)
--- a/test/test_arith.h Sun Nov 24 03:32:53 2024 -0500 +++ b/test/test_arith.h Sun Nov 24 11:15:59 2024 +0000 @@ -1,3 +1,5 @@ +#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) \ { \ @@ -13,7 +15,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, 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); \ @@ -60,7 +62,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, (orig_a[i] + orig_b[i] + 1) / 2) \ + 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]))