1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:17:35 +00:00

LibCrypto: Make UnsignedBigInteger as fast as architecturally possible

This commit attempts to make UnsignedBigInteger as fast as possible
without changing the underlaying architecture.
This effort involves
- Preallocating space for vector operations
- Avoiding calls to computationally expensive functions
- Inlining or flattening functions (sensibly)
This commit is contained in:
AnotherTest 2020-04-29 22:35:54 +04:30 committed by Andreas Kling
parent 4d932ce701
commit c9321b4f00
2 changed files with 16 additions and 13 deletions

View file

@ -90,7 +90,7 @@ UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) con
word_addition_result++; word_addition_result++;
} }
carry = carry_out; carry = carry_out;
result.m_words.append(word_addition_result); result.m_words.unchecked_append(word_addition_result);
} }
for (size_t i = shorter->length(); i < longer->length(); ++i) { for (size_t i = shorter->length(); i < longer->length(); ++i) {
@ -100,10 +100,10 @@ UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) con
if (word_addition_result < longer->m_words[i]) { if (word_addition_result < longer->m_words[i]) {
carry = 1; carry = 1;
} }
result.m_words.append(word_addition_result); result.m_words.unchecked_append(word_addition_result);
} }
if (carry) { if (carry) {
result.m_words.append(carry); result.m_words.unchecked_append(carry);
} }
return result; return result;
} }
@ -149,7 +149,7 @@ UnsignedBigInteger UnsignedBigInteger::minus(const UnsignedBigInteger& other) co
* So to multiple x*y, we go over each '1' bit in x (say the i'th bit), * So to multiple x*y, we go over each '1' bit in x (say the i'th bit),
* and add y<<i to the result. * and add y<<i to the result.
*/ */
UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigInteger& other) const FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigInteger& other) const
{ {
UnsignedBigInteger result; UnsignedBigInteger result;
// iterate all bits // iterate all bits
@ -175,7 +175,7 @@ UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigInteger& o
* so we set the ith bit in the quotient and reduce divisor<<i from the dividend. * so we set the ith bit in the quotient and reduce divisor<<i from the dividend.
* When we're done, what's left from the dividend is the remainder. * When we're done, what's left from the dividend is the remainder.
*/ */
UnsignedDivisionResult UnsignedBigInteger::divided_by(const UnsignedBigInteger& divisor) const FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(const UnsignedBigInteger& divisor) const
{ {
UnsignedBigInteger leftover_dividend(*this); UnsignedBigInteger leftover_dividend(*this);
UnsignedBigInteger quotient; UnsignedBigInteger quotient;
@ -205,7 +205,7 @@ void UnsignedBigInteger::set_bit_inplace(size_t bit_index)
m_words.ensure_capacity(word_index); m_words.ensure_capacity(word_index);
for (size_t i = length(); i <= word_index; ++i) { for (size_t i = length(); i <= word_index; ++i) {
m_words.append(0); m_words.unchecked_append(0);
} }
m_words[word_index] |= (1 << inner_word_index); m_words[word_index] |= (1 << inner_word_index);
} }
@ -236,15 +236,18 @@ UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const
return result; return result;
} }
UnsignedBigInteger UnsignedBigInteger::shift_left_by_n_words(const size_t number_of_words) const ALWAYS_INLINE UnsignedBigInteger UnsignedBigInteger::shift_left_by_n_words(const size_t number_of_words) const
{ {
// shifting left by N words means just inserting N zeroes to the beginning of the words vector // shifting left by N words means just inserting N zeroes to the beginning of the words vector
UnsignedBigInteger result; UnsignedBigInteger result;
result.m_words.ensure_capacity(number_of_words + length());
for (size_t i = 0; i < number_of_words; ++i) { for (size_t i = 0; i < number_of_words; ++i) {
result.m_words.append(0); result.m_words.unchecked_append(0);
} }
for (size_t i = 0; i < length(); ++i) { for (size_t i = 0; i < length(); ++i) {
result.m_words.append(m_words[i]); result.m_words.unchecked_append(m_words[i]);
} }
return result; return result;
} }
@ -252,7 +255,7 @@ UnsignedBigInteger UnsignedBigInteger::shift_left_by_n_words(const size_t number
/** /**
* Returns the word at a requested index in the result of a shift operation * Returns the word at a requested index in the result of a shift operation
*/ */
u32 UnsignedBigInteger::shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const ALWAYS_INLINE u32 UnsignedBigInteger::shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const
{ {
// "<= length()" (rather than length() - 1) is intentional, // "<= length()" (rather than length() - 1) is intentional,
// The result inedx of length() is used when calculating the carry word // The result inedx of length() is used when calculating the carry word

View file

@ -34,7 +34,7 @@
namespace Crypto { namespace Crypto {
struct UnsignedDivisionResult; struct UnsignedDivisionResult;
constexpr size_t STARTING_WORD_SIZE = 128; constexpr size_t STARTING_WORD_SIZE = 512;
class UnsignedBigInteger { class UnsignedBigInteger {
public: public:
@ -86,8 +86,8 @@ public:
String to_base10() const; String to_base10() const;
private: private:
UnsignedBigInteger shift_left_by_n_words(const size_t number_of_words) const; ALWAYS_INLINE UnsignedBigInteger shift_left_by_n_words(const size_t number_of_words) const;
u32 shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const; ALWAYS_INLINE u32 shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const;
static constexpr size_t BITS_IN_WORD = 32; static constexpr size_t BITS_IN_WORD = 32;
AK::Vector<u32, STARTING_WORD_SIZE> m_words; AK::Vector<u32, STARTING_WORD_SIZE> m_words;