rcx

miscellaneous C library
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

commit 4992f6d8b0053151cdb7d3749025eaeb436033b8
parent 9cc888da8773533f9bf345fa2694e6b4ce61f04a
Author: Robert Russell <robert@rr3.xyz>
Date:   Sat,  4 Jan 2025 16:24:58 -0800

Add bit zips

Diffstat:
MMakefile | 2++
Minc/bits.h | 16++++++++++++++++
Asrc/bits.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,6 +5,7 @@ include config.mk SRC =\ src/alloc.c\ src/bench.c\ + src/bits.c\ src/conv.c\ src/debug.c\ src/dict/impl/table.c\ @@ -49,6 +50,7 @@ librcx.a: $(SRC:.c=.o) src/alloc.o: src/alloc.c inc/alloc.h inc/def.h inc/log.h inc/rcx.h inc/internal/util.h config.mk src/bench.o: src/bench.c inc/bench.h inc/def.h inc/log.h inc/rcx.h config.mk +src/bits.o: src/bits.c inc/bits.h inc/def.h inc/rcx.h config.mk src/conv.o: src/conv.c inc/conv.h inc/debug.h inc/def.h inc/rcx.h config.mk src/debug.o: src/debug.c inc/debug.h inc/def.h inc/rcx.h config.mk src/dict/impl/table.o: src/dict/impl/table.c inc/dict/impl/table.h $(TABLE_DEPS) config.mk diff --git a/inc/bits.h b/inc/bits.h @@ -18,6 +18,22 @@ static inline u32 r_rotr32(u32 n, uint c) { return (n >> (c&31u)) | (n << (-c&31 static inline u64 r_rotr64(u64 n, uint c) { return (n >> (c&63u)) | (n << (-c&63u)); } +/* ----- Bit zips ----- */ + +/* TODO: Provide 8, 16, and 32 bit as well? The naming gets awkward, and then + * there would be 28 functions! */ +/* TODO: The smaller of these (r_bz{0,1,2}, perhaps) should probably be static + * inline. */ + +u64 r_bz0(u64 f); +u64 r_bz1(u64 f, u64 u); +u64 r_bz2(u64 f, u64 u, u64 v); +u64 r_bz3(u64 f, u64 u, u64 v, u64 w); +u64 r_bz4(u64 f, u64 u, u64 v, u64 w, u64 x); +u64 r_bz5(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y); +u64 r_bz6(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y, u64 z); + + /* ----- Population count ----- */ /* The GCC builtin's do not use hardware popcnt unless an appropriate -march diff --git a/src/bits.c b/src/bits.c @@ -0,0 +1,63 @@ +#include "bits.h" +#include "rcx.h" + +/* To perform a bit zip with n inputs, we evaluate, over the integers mod 2 + * (where XOR is addition and AND is multiplication), a recursively-structured + * polynomial with n variables, 2^n terms, and coefficients f0,f1,...,f(2^n-1), + * the bits of the zipping function f. The pattern is illustrated below for the + * first few values of n. In principle, we do this independently for each of + * the 64 n-tuples of input bits, but C's bit-wise operators let us do all 64 + * evaluations in parallel. */ + +/* This is the constant polynomial f0. We use a two's complement trick to + * broadcast f0 to an entire u64. */ +static inline u64 bz0(u64 f) { + return !(f & 1u) - 1u; +} + +/* f0 ^ + * f1 & u */ +static inline u64 bz1(u64 f, u64 u) { + return bz0(f) ^ (bz0(f >> 1) & u); +} + +/* f0 ^ + * f1 & u ^ + * f2 & v ^ + * f3 & u & v */ +static inline u64 bz2(u64 f, u64 u, u64 v) { + return bz1(f, u) ^ (bz1(f >> 2, u) & v); +} + +/* f0 ^ + * f1 & u ^ + * f2 & v ^ + * f3 & u & v ^ + * f4 & w ^ + * f5 & u & w ^ + * f6 & v & w ^ + * f7 & u & v & w */ +static inline u64 bz3(u64 f, u64 u, u64 v, u64 w) { + return bz2(f, u, v) ^ (bz2(f >> 4, u, v) & w); +} + +/* Etc... */ +static inline u64 bz4(u64 f, u64 u, u64 v, u64 w, u64 x) { + return bz3(f, u, v, w) ^ (bz3(f >> 8, u, v, w) & x); +} + +static inline u64 bz5(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y) { + return bz4(f, u, v, w, x) ^ (bz4(f >> 16, u, v, w, x) & y); +} + +static inline u64 bz6(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y, u64 z) { + return bz5(f, u, v, w, x, y) ^ (bz5(f >> 32, u, v, w, x, y) & z); +} + +u64 r_bz0(u64 f) { return bz0(f); } +u64 r_bz1(u64 f, u64 u) { return bz1(f, u); } +u64 r_bz2(u64 f, u64 u, u64 v) { return bz2(f, u, v); } +u64 r_bz3(u64 f, u64 u, u64 v, u64 w) { return bz3(f, u, v, w); } +u64 r_bz4(u64 f, u64 u, u64 v, u64 w, u64 x) { return bz4(f, u, v, w, x); } +u64 r_bz5(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y) { return bz5(f, u, v, w, x, y); } +u64 r_bz6(u64 f, u64 u, u64 v, u64 w, u64 x, u64 y, u64 z) { return bz6(f, u, v, w, x, y, z); }