LibCrypto: Improve efficiency of UnsignedBigInteger::shift_left

Before:
- a separate Word element allocation of the underlying Vector<Word> was
necessary for every new word in a multi-word shift
- two additional temporary UnsignedBigInteger buffers were allocated
and passed through, including in downstream calls (e.g. Multiplication)
- an additional allocation and word shift for the carry
- FIXME note seems to point to some of these issues

After:
- main change is in LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp
- one single allocation per call, using shift_left_by_n_words
- only the input "number" and "output" need to be allocated by the
  caller
- downstream calls are adapted not to allocate or pass temporary
  buffers
- noticeable performance improvement when running TestBigInteger:
  0.41-0.42s (before) to 0.28-0.29s (after) Intel Core i9 laptop

Bonus: remove unused variables from UnsignedBigInteger::divided_by
- These were likely cut-and-paste artifacts from
  UnsignedBigInteger::multiplied_by; not caught by "unused-varible".

NOTE: making this change in a separate commit than shift_right, even if
it touches the same file BitwiseOperations.cpp since:
- it is a "bonus" addition: not necessary for fixing the shift_right
  bug, but logically unrelated to the shift_right code
- it brings a chain of downstream interface modifications (7 files),
  unrelated to shift_right
This commit is contained in:
Manuel Zahariev 2025-01-08 08:51:40 -08:00 committed by Ali Mohammad Pur
commit d2ea77c099
Notes: github-actions[bot] 2025-03-23 18:34:27 +00:00
9 changed files with 60 additions and 74 deletions

View file

@ -489,10 +489,8 @@ FLATTEN ErrorOr<UnsignedBigInteger> UnsignedBigInteger::try_bitwise_not_fill_to_
FLATTEN ErrorOr<UnsignedBigInteger> UnsignedBigInteger::try_shift_left(size_t num_bits) const
{
UnsignedBigInteger output;
UnsignedBigInteger temp_result;
UnsignedBigInteger temp_plus;
TRY(UnsignedBigIntegerAlgorithms::try_shift_left_without_allocation(*this, num_bits, temp_result, temp_plus, output));
TRY(UnsignedBigIntegerAlgorithms::try_shift_left_without_allocation(*this, num_bits, output));
return output;
}
@ -541,11 +539,9 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::as_n_bits(size_t n) const
FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(UnsignedBigInteger const& other) const
{
UnsignedBigInteger result;
UnsignedBigInteger temp_shift_result;
UnsignedBigInteger temp_shift_plus;
UnsignedBigInteger temp_shift;
UnsignedBigIntegerAlgorithms::multiply_without_allocation(*this, other, temp_shift_result, temp_shift_plus, temp_shift, result);
UnsignedBigIntegerAlgorithms::multiply_without_allocation(*this, other, temp_shift, result);
return result;
}
@ -562,11 +558,6 @@ FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(UnsignedBigInteger
return UnsignedDivisionResult { quotient, remainder };
}
UnsignedBigInteger temp_shift_result;
UnsignedBigInteger temp_shift_plus;
UnsignedBigInteger temp_shift;
UnsignedBigInteger temp_minus;
UnsignedBigIntegerAlgorithms::divide_without_allocation(*this, divisor, quotient, remainder);
return UnsignedDivisionResult { quotient, remainder };