将整数矩阵转换为位串?
Convert integer matrix to bitstring?
我有一个 4x4
整数矩阵(称为 tb
),我可以从 int64_t
位串(称为 state
)创建如下:
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
ipos -= 1;
tb[i][j] = (state >> (4*_pos)) & 0xf);
}
}
但是,一旦我从矩阵开始,我如何才能将其更改为位串?我希望通过整数矩阵,获取元素,创建它的 4 位十六进制表示,然后将其移动 (<<4
) 正确的次数和按位或 (|
) bitstring 与新的 state
bitstring,但我不确定如何执行此操作或者它是否是最佳方法。想法?
当然可以,按照你说的去做,像这样(未测试)
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
pos--;
state |= (uint64_t)tb[i][j] << (4 * pos);
}
}
这有一个相当长的依赖链,这不是很好,特别是如果你在 HPC 中。你可以把它分成几部分,比如上半部分和下半部分,然后最后把它们组合起来。作为奖励,这意味着移位在 32 位而不是 64 位上运行,这在某些平台上可能更快。
根据 tb
的类型,可能还有其他技巧,例如,如果每个条目都是一个字节,并且您可以使用两个 uint64_t
作为别名,那么您可以组合这些条目使用直线位操作(虽然它们 "reversed" 与最方便的顺序相比)。
例如,可能是这样的(未测试)(假设顺序颠倒,也可以按相同顺序完成)
uint64_t low, high; // inputs
uint64_t even = 0x00FF00FF00FF00FFULL;
uint64_t odd = ~even;
low = (low & even) | ((low & odd) >> 4);
high = (high & even) | ((high & odd) >> 4);
even = 0x0000FFFF0000FFFFULL;
odd = ~even;
low = (low & even) | ((low & odd) >> 8);
high = (high & even) | ((high & odd) >> 8);
low = (low & 0xFFFF) | (low >> 16);
high = (high & 0xFFFF) | (high >> 16);
return low | (high << 32);
如果允许特殊说明还有更短的方法,(未测试,再次颠倒顺序)
low = _pext_u64(low, 0x0F0F0F0F0F0F0F0FULL);
high = _pext_u64(high, 0x0F0F0F0F0F0F0F0FULL);
return low | (high << 32);
其他方式的相关转换同样简单,
low = _pdep_u64(bitstring & 0xFFFFFFFF, 0x0F0F0F0F0F0F0F0FULL);
high = _pdep_u64(bitstring >> 32, 0x0F0F0F0F0F0F0F0FULL);
如果您只是先反转半字节,这两者也适用于反转顺序,这也可以通过位操作来完成。
我有一个 4x4
整数矩阵(称为 tb
),我可以从 int64_t
位串(称为 state
)创建如下:
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
ipos -= 1;
tb[i][j] = (state >> (4*_pos)) & 0xf);
}
}
但是,一旦我从矩阵开始,我如何才能将其更改为位串?我希望通过整数矩阵,获取元素,创建它的 4 位十六进制表示,然后将其移动 (<<4
) 正确的次数和按位或 (|
) bitstring 与新的 state
bitstring,但我不确定如何执行此操作或者它是否是最佳方法。想法?
当然可以,按照你说的去做,像这样(未测试)
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
pos--;
state |= (uint64_t)tb[i][j] << (4 * pos);
}
}
这有一个相当长的依赖链,这不是很好,特别是如果你在 HPC 中。你可以把它分成几部分,比如上半部分和下半部分,然后最后把它们组合起来。作为奖励,这意味着移位在 32 位而不是 64 位上运行,这在某些平台上可能更快。
根据 tb
的类型,可能还有其他技巧,例如,如果每个条目都是一个字节,并且您可以使用两个 uint64_t
作为别名,那么您可以组合这些条目使用直线位操作(虽然它们 "reversed" 与最方便的顺序相比)。
例如,可能是这样的(未测试)(假设顺序颠倒,也可以按相同顺序完成)
uint64_t low, high; // inputs
uint64_t even = 0x00FF00FF00FF00FFULL;
uint64_t odd = ~even;
low = (low & even) | ((low & odd) >> 4);
high = (high & even) | ((high & odd) >> 4);
even = 0x0000FFFF0000FFFFULL;
odd = ~even;
low = (low & even) | ((low & odd) >> 8);
high = (high & even) | ((high & odd) >> 8);
low = (low & 0xFFFF) | (low >> 16);
high = (high & 0xFFFF) | (high >> 16);
return low | (high << 32);
如果允许特殊说明还有更短的方法,(未测试,再次颠倒顺序)
low = _pext_u64(low, 0x0F0F0F0F0F0F0F0FULL);
high = _pext_u64(high, 0x0F0F0F0F0F0F0F0FULL);
return low | (high << 32);
其他方式的相关转换同样简单,
low = _pdep_u64(bitstring & 0xFFFFFFFF, 0x0F0F0F0F0F0F0F0FULL);
high = _pdep_u64(bitstring >> 32, 0x0F0F0F0F0F0F0F0FULL);
如果您只是先反转半字节,这两者也适用于反转顺序,这也可以通过位操作来完成。