SignedBigInteger::operator==(const UnsignedBigInteger&) was rejecting
all negative value before testing for equality. It now accepts negative
zero and test for a value equality with the UnsignedBigInteger.
Instead we just use a specific constructor. With this set of
constructors using curly braces for constructing is highly recommended.
As then it will not do too many implicit conversions which could lead to
unexpected loss of data or calling the much slower double constructor.
Also to ensure we don't feed (Un)SignedBigInteger infinities we throw
RangeError earlier for Durations.
This means it can take any (un)signed word of size at most Word.
This means the constructor can be disambiguated if we were to add a
double constructor :^).
This requires a change in just one test.
This allows using different options for rounding, like IEEE
roundTiesToEven, which is the mode that JS requires.
Also fix that the last word read from the bigint for the mantissa could
be shifted incorrectly leading to incorrect results.
SignedBigInteger can immediately use this by just negating the double if
the sign bit is set.
For simple cases (below 2^53) we can just convert via an u64, however
above that we need to extract the top 53 bits and use those as the
mantissa.
This function currently does not behave exactly as the JS spec specifies
however it is much less naive than the previous implementation.
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).
No functional changes.
These are mostly minor mistakes I've encountered while working on the
removal of StringView(char const*). The usage of builder.put_string over
Format<FormatString>::format is preferrable as it will avoid the
indirection altogether when there's no formatting to be done. Similarly,
there is no need to do format(builder, "{}", number) when
builder.put_u64(number) works equally well.
Additionally a few Strings where only constant strings were used are
replaced with StringViews.
If a big integer were to become negative zero, set the sign to instead
be positive. This prevents odd scenarios where users of signed big ints
would falsely think the result of some big int arithmetic is negative.
Removes the UnsignedBigInteger overloads of
SignedBigInteger::binary_{and,or,xor}(). They're now unused, and they
also didn't work when *this was negative.
We went through some trouble to make & and | work right. Reimplement ^
in terms of & and | to make ^ work right as well.
This is less fast than a direct implementation, but let's get things
working first.
Similar to the bitwise_and change, but we have to be careful to
sign-extend two's complement numbers only up to the highest set bit
in the positive number.
Bitwise and is defined in terms of two's complement, so some converting
needs to happen for SignedBigInteger's sign/magnitude representation to
work out.
UnsignedBigInteger::bitwise_not() is repurposed to convert all
high-order zero bits to ones up to a limit, for the two's complement
conversion to work.
Fixes test262/test/language/expressions/bitwise-and/bigint.js.
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()).
In order to reduce our reliance on __builtin_{ffs, clz, ctz, popcount},
this commit removes all calls to these functions and replaces them with
the equivalent functions in AK/BuiltinWrappers.h.
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
Currently, we get the following results
-1 - -2 = -1
-2 - -1 = 1
Correct would be:
-1 - -2 = 1
-2 - -1 = -1
This was already attempted to be fixed in 7ed8970, but that change was
incorrect. This directly translates to LibJS BigInts having the same
incorrect behavior - it even was tested.
We never really needed the 512 words in the first place, and this does
reduce the stack allocations in montgomery modular power from 32Kb to
a more manageable 2Kb :^)
Note that the 32 words size doesn't provide any performance benefits or
drawbacks compared to other values. All values seem to have equivalent
performances (the tested values were 1, 2, 4, ..., 512). But since the
previous value of 512 was definitely too big, let's reduce it for now!
This algorithm allows for much faster computations of modular powers
(around a 5x-10x speedup of the Crypto test). However, it is only valid
for odd modulo values, and therefore the old algorithm must be kept for
computations involving even modulo values.