mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:07:34 +00:00
LibCrypto: Add a constructor to (Un)SignedBigInteger taking a double
For now this will assume that the double given is exactly representable as an integer, so no NaN, infinity or rounding.
This commit is contained in:
parent
c87d10365b
commit
528891bf69
5 changed files with 161 additions and 8 deletions
|
@ -864,6 +864,80 @@ TEST_CASE(to_double)
|
|||
#undef EXPECT_TO_EQUAL_DOUBLE
|
||||
}
|
||||
|
||||
TEST_CASE(bigint_from_double)
|
||||
{
|
||||
{
|
||||
Crypto::UnsignedBigInteger from_zero { 0.0 };
|
||||
EXPECT(from_zero.is_zero());
|
||||
EXPECT(!from_zero.is_invalid());
|
||||
}
|
||||
|
||||
#define SURVIVES_ROUND_TRIP_UNSIGNED(double_value) \
|
||||
{ \
|
||||
Crypto::UnsignedBigInteger bigint { (double_value) }; \
|
||||
EXPECT_EQ(bigint.to_double(), (double_value)); \
|
||||
}
|
||||
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(0.0);
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(1.0);
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(100000.0);
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(1000000000000.0);
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(10000000000000000000.0);
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(NumericLimits<double>::max());
|
||||
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x4340000000000002ULL));
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x4340000000000001ULL));
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x4340000000000000ULL));
|
||||
|
||||
// Failed on last bits of mantissa
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x7EDFFFFFFFFFFFFFULL));
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x7ed5555555555555ULL));
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x7EDCBA9876543210ULL));
|
||||
|
||||
// Has exactly exponent of 32
|
||||
SURVIVES_ROUND_TRIP_UNSIGNED(bit_cast<double>(0x41f22f74e0000000ULL));
|
||||
|
||||
#define SURVIVES_ROUND_TRIP_SIGNED(double_value) \
|
||||
{ \
|
||||
Crypto::SignedBigInteger bigint_positive { (double_value) }; \
|
||||
EXPECT_EQ(bigint_positive.to_double(), (double_value)); \
|
||||
Crypto::SignedBigInteger bigint_negative { -(double_value) }; \
|
||||
EXPECT_EQ(bigint_negative.to_double(), -(double_value)); \
|
||||
EXPECT(bigint_positive != bigint_negative); \
|
||||
bigint_positive.negate(); \
|
||||
EXPECT(bigint_positive == bigint_negative); \
|
||||
}
|
||||
|
||||
{
|
||||
// Negative zero should be converted to positive zero
|
||||
double const negative_zero = bit_cast<double>(0x8000000000000000);
|
||||
|
||||
// However it should give a bit exact +0.0
|
||||
Crypto::SignedBigInteger from_negative_zero { negative_zero };
|
||||
EXPECT(from_negative_zero.is_zero());
|
||||
EXPECT(!from_negative_zero.is_negative());
|
||||
double result = from_negative_zero.to_double();
|
||||
EXPECT_EQ(result, 0.0);
|
||||
EXPECT_EQ(bit_cast<u64>(result), 0ULL);
|
||||
}
|
||||
|
||||
SURVIVES_ROUND_TRIP_SIGNED(1.0);
|
||||
SURVIVES_ROUND_TRIP_SIGNED(100000.0);
|
||||
SURVIVES_ROUND_TRIP_SIGNED(-1000000000000.0);
|
||||
SURVIVES_ROUND_TRIP_SIGNED(10000000000000000000.0);
|
||||
SURVIVES_ROUND_TRIP_SIGNED(NumericLimits<double>::max());
|
||||
SURVIVES_ROUND_TRIP_SIGNED(NumericLimits<double>::lowest());
|
||||
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x4340000000000002ULL));
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x4340000000000001ULL));
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x4340000000000000ULL));
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x7EDFFFFFFFFFFFFFULL));
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x7ed5555555555555ULL));
|
||||
SURVIVES_ROUND_TRIP_SIGNED(bit_cast<double>(0x7EDCBA9876543210ULL));
|
||||
|
||||
#undef SURVIVES_ROUND_TRIP_SIGNED
|
||||
#undef SURVIVES_ROUND_TRIP_UNSIGNED
|
||||
}
|
||||
namespace AK {
|
||||
|
||||
template<>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue