根据位掩码拆分多个字节

Split multiple bytes according to bit masks

我正在尝试根据位掩码拆分字节。

考虑这两个字节(二进制中的 1000 为 short int):

11101000

00000011

以及这三个面具:

00000011

11111111

00111111

我想做的是把原来的两个字节按照提供的掩码拆分成三个字节

结果应该是:

00000000 第一个字节

11111010第二个(原始字节1和2因为掩码而合并)

00000000第三个(其余位用零填充)

用 Java 或 C 最简单的方法是什么?

在 C 中,如果使用 x86,这是单个 pdep 操作。

#include <immintrin.h>

int msk(int num) {
    int src =  0b0000001111101000;
    int mask = 0b001111111111111100000011;

    int result = _pdep_u32(src,mask);

    int expected_result = 0b000000001111101000000000;

    if (result == expected_result) {
        return 1; // returns this
    } else {
        return 0;
    }
}

参见 _pdep_u32 in Intel Intrinsic Guide

https://godbolt.org/z/b6E6M8518


如果您的 inputs/output 是恰好 4 个字节的数组,您可以 memcpy 从数组到 int 并返回。

如果您不仅针对 x86,还针对没有 BMI2 的旧 x86,或者想要 Java 解决方案,则必须从 PDEP 文档实施此算法:

tmp := a
dst := 0
m := 0
k := 0
DO WHILE m < 32
    IF mask[m] == 1
        dst[m] := tmp[k]
        k := k + 1
    FI
    m := m + 1
OD

dst[m]tmp[k] 可以通过数组索引和位移来完成,具体 dst[m] := tmp[k] 是(假设 8 位字节):

unsigned char bit = (dst[k/8] >> (k%8)) & 1;
dst[m/8] |= bit << (m%8)

请注意,直接实现不仅有点复杂,而且效率也较低,因为 pdep 是单个 CPU 指令。但是我不确定 Java 是否公开它,如果没有,那么使用 JNI 调用 C 实现是否值得。