This concept is rarely used in codebase and very much error-prone
if you forget to check it.
Instead, make it so that operations that would produce invalid integers
return an error instead.
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 fixes the issue with the exported data having a leading zero,
causing RSA::encrypt to trim the block down, and ruining the encryption.
Fixes#2691 :^)
All the magic is happening in a "while != 0" loop, so we ended up with
an empty string for zero-value BigIntegers. Now we just check that
upfront and return early.
Use Vector::resize_and_keep_capacity() to resize BigInt vectors to just
the right size without risking deallocation. Then do direct indexed
accesses to the underlying words (or use memset/memcpy.)
This gives a ~40% speed-up on the RSA tests in "test-crypto -t pk" :^)
This changes the plus, minus, etc... operators from UnsignedBigInteger to use a
static helper method. The static methods do not allocate any variables, instead
all the required BigInteger output and temporary variables are required on call
as parameters.
This change already optimizes the number of allocations in complex operations
such as multiply or divide, by having a single allocation per call (instead of
one per loop).
This new API also provides a way to limit the number of allocations for complex
computations in other parts of the code. This is done by using these helpers in
any place that currently makes use of the standard operators.
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)
There was a bug when dealing with a carry when the addition
result for the current word was UINT32_MAX.
This commit also adds a regression test for the bug.