c++ - "Isolate"来自 64 位数字的特定行/列/对角线

标签 c++ performance 64-bit bit-manipulation bitboard

好的,让我们考虑一个 64 位的数字,它的位组成一个 8x8 的表。

例如

0 1 1 0 1 0 1 0 0 1 1 0 1 0 1 1 0 1 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 1 1 0 1 0 1 0 0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 0

写成

a b c d e f g h
----------------
0 1 1 0 1 0 1 0
0 1 1 0 1 0 1 1 
0 1 1 1 1 0 1 0 
0 1 1 0 1 0 1 0 
1 1 1 0 1 0 1 0 
0 1 1 0 1 0 1 0 
0 1 1 0 1 1 1 0 
0 1 1 0 1 0 1 0

现在,如果我们只想隔离例如d 列(00100000)(或任何行/对角线)?

这可以做到吗?如果可以,怎么做?


提示:

最佳答案

这是一个只有 4 个主要步骤的解决方案:

const uint64_t column_mask = 0x8080808080808080ull;
const uint64_t magic = 0x2040810204081ull;

int get_col(uint64_t board, int col) {
    uint64_t column = (board << col) & column_mask;
    column *= magic;
    return (column >> 56) & 0xff;
}

它是这样工作的:

  • 板被移动以使列与左侧对齐
  • 它被屏蔽为仅包含所需的列 (0..8)
  • 乘以一个魔数(Magic Number),将所有原始位推到左侧
  • 最左边的字节向右移动

选择魔数(Magic Number)以仅复制所需的位,并让其余的位落入未使用的位置/溢出该数字。这个过程看起来像这样(数字是位“ID”,而不是数字本身):

original column: ...1.......2.......3.......4.......5.......6.......7.......8....
aligned column:  1.......2.......3.......4.......5.......6.......7.......8.......
multiplied:      123456782345678.345678..45678...5678....678.....78......8.......
shifted to right:........................................................12345678

如果你添加 const 关键字,汇编实际上变得非常好:

get_col:
.LFB7:
        .cfi_startproc
        movl    %esi, %ecx
        movabsq $-9187201950435737472, %rax
        salq    %cl, %rdi
        andq    %rax, %rdi
        movabsq $567382630219905, %rax
        imulq   %rax, %rdi
        shrq    $56, %rdi
        movl    %edi, %eax
        ret

无分支,无外部数据,每次计算大约 0.4ns。

编辑:使用 NPE 的解决方案作为基线大约需要 6 分之一的时间(下一个最快的)

关于c++ - "Isolate"来自 64 位数字的特定行/列/对角线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14537831/

相关文章:

c++ - 在 C++ 中重写转换操作

performance - 加快 POVRAY 图像创建的示例配置

java - 性能工程 : Inconsistent results in measuring turnaround time

c# - 如何配置我的项目以在 64 位和 32 位计算机上运行

采用依赖于模板参数的 std::function 的 C++11 模板函数

c++ - CMake 不再查找静态 Boost 库

c++ - DirectX 10.1/C++ : How to render text on sprite over ID3D10Resource* textures?

performance - Perl中拆分超长音译的效率

debugging - 对于 64 位进程,kb 显示什么?

linux - 在 x64 CentOS 上构建 Cairo 时遇到问题