LibCrypo: Simplify mixed-sign bitwise_or

No behavior change.
This commit is contained in:
Nico Weber 2022-01-18 09:22:07 -05:00 committed by Ali Mohammad Pur
parent 2392f65345
commit e09f74903e
2 changed files with 14 additions and 5 deletions

View file

@ -173,12 +173,20 @@ FLATTEN SignedBigInteger SignedBigInteger::bitwise_or(const SignedBigInteger& ot
if (!is_negative() && !other.is_negative())
return { unsigned_value().bitwise_or(other.unsigned_value()), false };
size_t index = max(unsigned_value().one_based_index_of_highest_set_bit(), other.unsigned_value().one_based_index_of_highest_set_bit());
if (is_negative() && !other.is_negative())
return { unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1).bitwise_or(other.unsigned_value()).bitwise_not_fill_to_one_based_index(index).plus(1), true };
// -A | B == (~A + 1) | B == ~(A - 1) | B. The result is negative, so need to two's complement at the end to move the sign into the m_sign field.
// That can be simplified to:
// -(-A | B) == ~(~(A - 1) | B) + 1 = (A - 1) & ~B + 1
// This saves one ~.
if (is_negative() && !other.is_negative()) {
size_t index = unsigned_value().one_based_index_of_highest_set_bit();
return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().bitwise_not_fill_to_one_based_index(index)).plus(1), true };
}
if (!is_negative() && other.is_negative())
return { unsigned_value().bitwise_or(other.unsigned_value().bitwise_not_fill_to_one_based_index(index).plus(1)).bitwise_not_fill_to_one_based_index(index).plus(1), true };
// -(A | -B) == ~A & (B - 1) + 1
if (!is_negative() && other.is_negative()) {
size_t index = other.unsigned_value().one_based_index_of_highest_set_bit();
return { unsigned_value().bitwise_not_fill_to_one_based_index(index).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
}
return { unsigned_value().minus(1).bitwise_and(other.unsigned_value().minus(1)).plus(1), true };
}

View file

@ -44,6 +44,7 @@ describe("correct behavior", () => {
expect(1n | 2n).toBe(3n);
expect(0n | -1n).toBe(-1n);
expect(0n | -2n).toBe(-2n);
expect(5n ^ 3n).toBe(6n);