从位置i开始生产具有n个掩模的最快方法

Vin*_*ent 9 c++ optimization bit-manipulation bitmask

什么是最快的方法(在常见的现代架构上的cpu周期方面),len从位置开始生成位设置为1 的掩码pos:

template <class UIntType>
constexpr T make_mask(std::size_t pos, std::size_t len)
{
    // Body of the function
}

// Call of the function
auto mask = make_mask<uint32_t>(4, 10);
// mask = 00000000 00000000 00111111 11110000 
// (in binary with MSB on the left and LSB on the right)
Run Code Online (Sandbox Code Playgroud)

另外,是否有任何编译器内在函数或BMI函数可以帮助?

KII*_*IIV 7

最快的方式?我会用这样的东西:

template <class T>
constexpr T make_mask(std::size_t pos, std::size_t len)
{
  return ((static_cast<T>(1) << len)-1) << pos;
}
Run Code Online (Sandbox Code Playgroud)

  • 小建议:将 `(T)1` 更改为 `static_cast&lt;T&gt;(1)` 会使括号不那么像 LISP,并且可能更易于阅读。(就我个人而言,我会使用 static_cast,但 C 风格的类型转换在这里也可以)。 (2认同)

ric*_*ici 5

如果"开始pos",你的意思是面具的最低位是在与2个对应的位置POS(如你的例子):

((UIntType(1) << len) - UIntType(1)) << pos
Run Code Online (Sandbox Code Playgroud)

如果有可能len≥位数UIntType,请通过测试避免未​​定义的行为:

(((len < std::numeric_limits<UIntType>::digits)
     ? UIntType(1)<<len
     : 0) - UIntType(1)) << pos
Run Code Online (Sandbox Code Playgroud)

(如果也可能posstd::numeric_limits<UIntType>::digits,则需要进行另一次三元运算测试.)

你也可以使用:

(UIntType(1)<<(len>>1)<<((len+1)>>1) - UIntType(1)) << pos
Run Code Online (Sandbox Code Playgroud)

这避免了三元运算,代价是三个额外的班次运营商; 我怀疑它是否会更快但需要仔细的基准测试才能确定.