我的建议是使用查找表来加速处理。
另一件要注意的事情是,根据当前矩阵定义,最大尺寸将为8x8位。这适用于uint64_t,因此我们可以利用这一点,特别是在使用64位平台时。
我已经设计出一个简单的示例,使用查找表,您可以在下面找到并使用:
http://www.tutorialspoint.com/compile_cpp11_online.php在线编译器。
示例代码
#include <iostream>
#include <bitset>
#include <stdint.h>
#include <assert.h>
using std::cout;
using std::endl;
using std::bitset;
static uint64_t lut[256];
template<int N>
void print_arr(const uint8_t (&arr)[N]){
for(int i=0; i < N; ++i){
cout << bitset<8>(arr[i]) << endl;
}
}
template<int N>
void transpose_bitmatrix(const uint8_t (&matrix)[N], uint8_t (&transposed)[8]){
assert(N <= 8);
uint64_t value = 0;
for(int i=0; i < N; ++i){
value = (value << 1) + lut[matrix[i]];
}
for(int i=0; i < 8; ++i){
transposed[i] = (value >> (i * 8)) & 0xFF;
}
}
void calculate_lut(void){
for(uint64_t i = 0; i < 256; ++i){
auto b = std::bitset<8>(i);
auto v = std::bitset<64>(0);
for(int bit=0; bit < 8; ++bit){
if(b.test(bit)){
v.set((7 - bit) * 8);
}
}
lut[i] = v.to_ullong();
}
}
int main()
{
calculate_lut();
const uint8_t matrix[] = {
0b01010101,
0b00110011,
0b00001111,
};
uint8_t transposed[8];
transpose_bitmatrix(matrix, transposed);
print_arr(transposed);
return 0;
}
工作原理
您的3x8矩阵将被转置为8x3矩阵,并表示为一个8x8数组。问题在于,您想要将位(“水平”表示)转换为垂直表示,并分散在几个字节中。
正如我上面所提到的,我们可以利用输出(8x8)总是适合于uint64_t的事实。我们将利用此功能,因为现在我们可以使用uint64_t来写入8字节数组,但我们也可以用它来添加、异或等,因为我们可以对64位整数执行基本算术运算。
您3x8矩阵(输入)中的每个条目都有8位宽度,为了优化处理,我们首先生成256条目查找表(每个字节值)。该条目本身是一个uint64_t,将包含位的旋转版本。
例如:
字节= 0b01001111 = 0x4F
lut [0x4F] = 0x0001000001010101 =(uint8_t []){0,1,0,0,1,1,1,1}
现在进行计算:
对于计算,我们使用uint64_t,但请记住,在水下它将表示uint8_t [8]数组。我们简单地移动当前值(从0开始),查找第一个字节并将其添加到当前值中。
这里的“神奇”之处在于,查找表中uint64_t的每个字节只会是1或0,因此它仅设置最低有效位(每个字节)。移动uint64_t将移动每个字节,只要我们确保不要这样做超过8次!,我们可以单独对每个字节执行操作。
问题
正如某人在评论中指出的那样:Translate(Translate(M))!= M,所以如果您需要这个,则需要进行一些额外的工作。
通过直接映射uint64_t而不是uint8_t [8]数组,性能可以得到改进,因为它省略了一个“安全复制”,以防止对齐问题。
0b00000000
而不是0b00000001
?为什么第二行是0b00000100
而不是0b00000010
?... - m.s.