LibJS+LibCrypto: Use a bitwise approach for BigInt's as*IntN methods

This speeds up expressions such as `BigInt.asIntN(0x4000000000000, 1n)`
(#3615). And those involving very large bigints.
This commit is contained in:
Jess
2025-03-19 10:31:39 +13:00
committed by Jelle Raaijmakers
parent 92d0cd3c7c
commit 12cbefbee7
Notes: github-actions[bot] 2025-03-20 08:45:14 +00:00
9 changed files with 110 additions and 33 deletions

View File

@@ -473,10 +473,15 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_xor(UnsignedBigInteger co
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::bitwise_not_fill_to_one_based_index(size_t size) const
{
return MUST(try_bitwise_not_fill_to_one_based_index(size));
}
FLATTEN ErrorOr<UnsignedBigInteger> UnsignedBigInteger::try_bitwise_not_fill_to_one_based_index(size_t size) const
{
UnsignedBigInteger result;
UnsignedBigIntegerAlgorithms::bitwise_not_fill_to_one_based_index_without_allocation(*this, size, result);
TRY(UnsignedBigIntegerAlgorithms::bitwise_not_fill_to_one_based_index_without_allocation(*this, size, result));
return result;
}
@@ -506,6 +511,33 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_right(size_t num_bits) cons
return output;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::as_n_bits(size_t n) const
{
if (auto const num_bits = one_based_index_of_highest_set_bit(); n >= num_bits)
return *this;
UnsignedBigInteger output;
output.set_to(*this);
auto const word_index = n / BITS_IN_WORD;
auto const bits_to_keep = n % BITS_IN_WORD;
auto const bits_to_discard = BITS_IN_WORD - bits_to_keep;
output.m_words.resize(word_index + 1);
auto const last_word = output.m_words[word_index];
Word new_last_word = 0;
// avoid UB from a 32 bit shift on a u32
if (bits_to_keep != 0)
new_last_word = last_word << bits_to_discard >> bits_to_discard;
output.m_words[word_index] = new_last_word;
return output;
}
FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
{
UnsignedBigInteger result;