LibJS+LibCrypto: Fix SignedBitInteger::bitwise_not and use it in LibJS
Bitwise operators are defined on two's complement, but SignedBitInteger uses sign-magnitude. Correctly convert between the two. Let LibJS delegate to SignedBitInteger for bitwise_not, like it does for all other bitwise_ operations on bigints. No behavior change (LibJS is now the only client of SignedBitInteger::bitwise_not()).
This commit is contained in:
parent
ec37eadb39
commit
945d962322
Notes:
sideshowbarker
2024-07-17 20:40:21 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/945d9623223 Pull-request: https://github.com/SerenityOS/serenity/pull/11996 Reviewed-by: https://github.com/alimpfard
4 changed files with 15 additions and 5 deletions
|
@ -467,6 +467,12 @@ TEST_CASE(test_bigint_bitwise_and_different_lengths)
|
|||
EXPECT_EQ(num1.bitwise_and(num2), "1180290"_bigint);
|
||||
}
|
||||
|
||||
TEST_CASE(test_signed_bigint_bitwise_not)
|
||||
{
|
||||
EXPECT_EQ("3"_sbigint.bitwise_not(), "-4"_sbigint);
|
||||
EXPECT_EQ("-1"_sbigint.bitwise_not(), "0"_sbigint);
|
||||
}
|
||||
|
||||
TEST_CASE(test_signed_bigint_bitwise_and)
|
||||
{
|
||||
auto num1 = "-1234567"_sbigint;
|
||||
|
|
|
@ -160,7 +160,12 @@ FLATTEN SignedBigInteger SignedBigInteger::bitwise_xor(const UnsignedBigInteger&
|
|||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::bitwise_not() const
|
||||
{
|
||||
return { unsigned_value().bitwise_not(), !m_sign };
|
||||
// Bitwise operators assume two's complement, while SignedBigInteger uses sign-magnitude.
|
||||
// In two's complement, -x := ~x + 1.
|
||||
// Hence, ~x == -x -1 == -(x + 1).
|
||||
SignedBigInteger result = plus(SignedBigInteger { 1 });
|
||||
result.negate();
|
||||
return result;
|
||||
}
|
||||
|
||||
FLATTEN SignedBigInteger SignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
|
||||
|
|
|
@ -881,10 +881,7 @@ ThrowCompletionOr<Value> bitwise_not(GlobalObject& global_object, Value lhs)
|
|||
auto lhs_numeric = TRY(lhs.to_numeric(global_object));
|
||||
if (lhs_numeric.is_number())
|
||||
return Value(~TRY(lhs_numeric.to_i32(global_object)));
|
||||
auto big_integer_bitwise_not = lhs_numeric.as_bigint().big_integer();
|
||||
big_integer_bitwise_not = big_integer_bitwise_not.plus(Crypto::SignedBigInteger { 1 });
|
||||
big_integer_bitwise_not.negate();
|
||||
return Value(js_bigint(vm, big_integer_bitwise_not));
|
||||
return Value(js_bigint(vm, lhs_numeric.as_bigint().big_integer().bitwise_not()));
|
||||
}
|
||||
|
||||
// 13.5.4 Unary + Operator, https://tc39.es/ecma262/#sec-unary-plus-operator
|
||||
|
|
|
@ -40,6 +40,8 @@ describe("correct behavior", () => {
|
|||
expect(1n | 2n).toBe(3n);
|
||||
expect(5n ^ 3n).toBe(6n);
|
||||
expect(~1n).toBe(-2n);
|
||||
expect(~-1n).toBe(0n);
|
||||
|
||||
expect(5n << 2n).toBe(20n);
|
||||
expect(7n >> 1n).toBe(3n);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue