diff options
| author | Jeff Epler <jepler@gmail.com> | 2021-02-18 11:33:13 -0600 |
|---|---|---|
| committer | Jeff Epler <jepler@gmail.com> | 2021-02-18 11:33:13 -0600 |
| commit | c284728621fa28d4ef318d98db2b11cc95417e6a (patch) | |
| tree | d81041ea8e0c79749adb5bee13558a61420f1305 /shared-module | |
| parent | 9cf7d73c6c71df1e43d11d4f2f604a76f59365a8 (diff) | |
bit_transpose: Support from 2 to 7 strands, not just 8
Diffstat (limited to 'shared-module')
| -rw-r--r-- | shared-module/_bit_transpose/__init__.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/shared-module/_bit_transpose/__init__.c b/shared-module/_bit_transpose/__init__.c index e30f989b9..517d2d840 100644 --- a/shared-module/_bit_transpose/__init__.c +++ b/shared-module/_bit_transpose/__init__.c @@ -30,6 +30,12 @@ #include <stdlib.h> #include <string.h> +#ifdef __GNUC__ +#define FALLTHROUGH __attribute__((fallthrough)) +#else +#define FALLTHROUGH ((void)0) /* FALLTHROUGH */ +#endif + // adapted from "Hacker's Delight" - Figure 7-2 Transposing an 8x8-bit matrix // basic idea is: // > First, treat the 8x8-bit matrix as 16 2x2-bit matrices, and transpose each @@ -40,7 +46,57 @@ // > illustrated below. // We want a different definition of bit/byte order, deal with strides differently, etc. // so the code is heavily re-worked compared to the original. -static void transpose8(uint32_t *result, const uint8_t *src, int src_stride) { +static void transpose_var(uint32_t *result, const uint8_t *src, int src_stride, int num_strands) { + uint32_t x = 0, y = 0, t; + + src += (num_strands-1) * src_stride; + + switch(num_strands) { + case 7: + x |= *src << 16; + src -= src_stride; + FALLTHROUGH; + case 6: + x |= *src << 8; + src -= src_stride; + FALLTHROUGH; + case 5: + x |= *src; + src -= src_stride; + FALLTHROUGH; + case 4: + y |= *src << 24; + src -= src_stride; + FALLTHROUGH; + case 3: + y |= *src << 16; + src -= src_stride; + FALLTHROUGH; + case 2: + y |= *src << 8; + src -= src_stride; + y |= *src; + } + + t = (x ^ (x >> 7)) & 0x00AA00AA; x = x ^ t ^ (t << 7); + t = (y ^ (y >> 7)) & 0x00AA00AA; y = y ^ t ^ (t << 7); + + t = (x ^ (x >>14)) & 0x0000CCCC; x = x ^ t ^ (t <<14); + t = (y ^ (y >>14)) & 0x0000CCCC; y = y ^ t ^ (t <<14); + + t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F); + y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F); + x = t; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + x = __builtin_bswap32(x); + y = __builtin_bswap32(y); +#endif + result[0] = x; + result[1] = y; +} + +static void transpose_8(uint32_t *result, const uint8_t *src, int src_stride) { uint32_t x, y, t; y = *src; src += src_stride; @@ -70,14 +126,26 @@ static void transpose8(uint32_t *result, const uint8_t *src, int src_stride) { result[1] = y; } -static void bit_transpose(uint32_t *result, const uint8_t *src, size_t src_stride, size_t n) { +static void bit_transpose_8(uint32_t *result, const uint8_t *src, size_t src_stride, size_t n) { for(size_t i=0; i<n; i++) { - transpose8(result, src, src_stride); + transpose_8(result, src, src_stride); result += 2; src += 1; } } -void common_hal_bit_transpose_bit_transpose(uint8_t *result, const uint8_t *src, size_t n) { - bit_transpose((uint32_t*)(void*)result, src, n/8, n/8); +static void bit_transpose_var(uint32_t *result, const uint8_t *src, size_t src_stride, size_t n, int num_strands) { + for(size_t i=0; i<n; i++) { + transpose_var(result, src, src_stride, num_strands); + result += 2; + src += 1; + } +} + +void common_hal_bit_transpose_bit_transpose(uint8_t *result, const uint8_t *src, size_t inlen, size_t num_strands) { + if(num_strands == 8) { + bit_transpose_8((uint32_t*)(void*)result, src, inlen/8, inlen/8); + } else { + bit_transpose_var((uint32_t*)(void*)result, src, inlen/num_strands, inlen/num_strands, num_strands); + } } |
