// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include // One bitshuffle block, transformed by whichever of the two vendored implementations is SIMD on // this architecture. The two write byte-identical output and each decodes the other's, so the file // format does not depend on the build host. // // bitshuffle_hperf is x86-only: outside SSE2 its whole vector body is compiled out and what remains // is a scalar fallback. The classic bitshuffle has an aarch64 NEON path (bitshuffle_core.c, // USEARMNEON), so aarch64 uses that instead - measured against the hperf scalar fallback it is // ~2.5x on encode and ~1.7x on decode. Everywhere else hperf wins outright (~2x over classic SSE2), // so it stays the default. // // The condition mirrors USEARMNEON in bitshuffle_core.c exactly. With NEON off the classic path // falls back to a scalar of its own that is slower than hperf's, so it must not be selected then. #if (defined(__ARM_NEON__) || (__ARM_NEON)) && defined(__aarch64__) // The classic entry points allocate their own block-sized scratch, so the caller's goes unused. inline int64_t JFJochBitShuffleBlock(char *out, const char *in, char *, size_t size, size_t elem_size) { return bshuf_trans_bit_elem(in, out, size, elem_size); } inline int64_t JFJochBitUnshuffleBlock(char *out, const char *in, char *, size_t size, size_t elem_size) { return bshuf_untrans_bit_elem(in, out, size, elem_size); } #else inline int64_t JFJochBitShuffleBlock(char *out, const char *in, char *scratch, size_t size, size_t elem_size) { return bitshuf_encode_block(out, in, scratch, size, elem_size); } inline int64_t JFJochBitUnshuffleBlock(char *out, const char *in, char *scratch, size_t size, size_t elem_size) { return bitshuf_decode_block(out, in, scratch, size, elem_size); } #endif