diff options
author | davidot <davidot@serenityos.org> | 2022-08-25 23:37:09 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-08-26 19:18:26 +0100 |
commit | 528891bf69f6d209b6884735fb6a47b17d1a81a7 (patch) | |
tree | 9718bd5407e9ef23e6d558c82e121734cbe89847 /Tests/LibCrypto/TestBigInteger.cpp | |
parent | c87d10365bec1d5f7314e9333826039070e3f280 (diff) | |
download | serenity-528891bf69f6d209b6884735fb6a47b17d1a81a7.zip |
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.
Diffstat (limited to 'Tests/LibCrypto/TestBigInteger.cpp')
-rw-r--r-- | Tests/LibCrypto/TestBigInteger.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/Tests/LibCrypto/TestBigInteger.cpp b/Tests/LibCrypto/TestBigInteger.cpp index e28fdf8b75..3332cc065e 100644 --- a/Tests/LibCrypto/TestBigInteger.cpp +++ b/Tests/LibCrypto/TestBigInteger.cpp @@ -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<> |