在位掩码中找到一个的位置 - Julia

Finding the location of ones in a bit mask - Julia

我有一系列值,每个值都存储为 UInt16。这些数字中的每一个都代表一个位掩码 - 这些数字是已发送到微处理器的命令,告诉它哪些引脚设置为高电平或低电平。我想解析这个命令箭头,以找出每次都将哪些引脚设置为高电平,以便以后更容易分析。

考虑示例值 0x3c00,十进制为 15360,二进制为 0011110000000000。目前我有以下功能

function read_message(hex_rep)
    return findall.(x -> x .== '1',bitstring(hex_rep))
end

UInt16 数组的每个元素都会调用它。有没有 better/more 有效的方法来做到这一点?

我可以建议将您的矢量填充到 Vector{UInt64} 中,然后使用它来手动构建 BitVector。以下应该主要工作(即使对于 UInt16 以外的输入元素类型),但我没有考虑您可能想要尊重的特定字节顺序:

julia> function read_messages(msgs)
           bytes = reinterpret(UInt8, msgs)
           N = length(bytes)
           nchunks, remaining = divrem(N, sizeof(UInt64))
           padded_bytes = zeros(UInt8, sizeof(UInt64) * cld(N, sizeof(UInt64)))
           copyto!(padded_bytes, bytes)
           b = BitVector(undef, N * 8)
           b.chunks = reinterpret(UInt64, padded_bytes)
           return b
       end
read_messages (generic function with 1 method)

julia> msgs
2-element Vector{UInt16}:
 0x3c00
 0x8000

julia> read_messages(msgs)
32-element BitVector:
 0
 0
 0
 0
 0
 0
 0
 0
 0
 ⋮
 0
 0
 0
 0
 0
 0
 0
 1


julia> read_messages(msgs) |> findall
5-element Vector{Int64}:
 11
 12
 13
 14
 32

julia> bitstring.(msgs)
2-element Vector{String}:
 "0011110000000000"
 "1000000000000000"

(摆脱不必要的 undef 位向量分配需要一些黑魔法,我相信。)

最佳方法可能取决于您希望如何处理十六进制值向量。但是这里有一种处理单个十六进制的方法,它比 OP 中的方法快得多:

 function readmsg(x::UInt16)
    N = count_ones(x)
    inds = Vector{Int}(undef, N)
    if N == 0
        return inds
    end
    k = trailing_zeros(x)
    x >>= k + 1
    i = N - 1
    inds[N] = n = 16 - k
    while i >= 1
        (x, r) = divrem(x, 0x2)
        n -= 1
        if r == 1
            inds[i] = n
            i -= 1
        end
    end
    return inds
end