如何用bitslice做算术运算?



使用bitvec crate,假设我有两个BitSlice:

let num1: &BitSlice = 10.view_bits::<Lsb0>();
let num2: &BitSlice = 9.view_bits::<Lsb0>();

是否有一种方法来运行位算术运算,如num1 - num2与这些?

我有在no-std环境中工作的限制,位片可能相当大,所以我不能将它们转换为数字,进行操作并转换回位表示。

bitvec过去包含加减法,但在0.18版本中删除了它们。此外,BitSlice上从来没有减法,只有加法。虽然上面提到它们应该被转移到一个单独的板条箱中,但我找不到这样的板条箱。所以,你需要自己实现它。

最简单(虽然肯定不是最有效)的方法是逐位遍历并执行操作。

例如,添加(改编自0.17.4版的代码):

/// May overflow.
pub fn add_assign(lhs: &mut BitSlice, rhs: &BitSlice) {
fn add_with_carry(a: bool, b: bool, carry: bool) -> (bool, bool) {
let result = u8::from(a) + u8::from(b) + u8::from(carry);
((result & 0b01) != 0, (result & 0b10) != 0)
}
let mut carry = false;
let extended_rhs = rhs.iter().by_vals().rev().chain(core::iter::repeat(false));
for (mut lhs_bit, rhs_bit) in lhs.iter_mut().rev().zip(extended_rhs) {
(*lhs_bit, carry) = add_with_carry(*lhs_bit, rhs_bit, carry);
}
}

请注意,除非您可以扩展片,否则无法防止溢出,而这需要BitVec和分配支持。

为了完整起见,我将添加我自己的减法函数:

pub fn subtract(lhs: &mut BitSlice, rhs: &BitSlice) {
let mut borrow = false;
for (mut l, r) in lhs
.iter_mut()
.rev()
.zip(rhs.iter().by_vals().rev().chain(core::iter::repeat(false)))
{
if borrow {
*l = !(*l);
borrow = *l;
}
*l = match (*l, r) {
(true, false) => true,
(false, true) => {
borrow = true;
true
}
(_, _) => false,
};
}
}

我可以为我的用例做一些假设,比如位顺序和lhs >= rhs,所以如果你要复制粘贴这些代码,请考虑这些情况。

最新更新