summaryrefslogtreecommitdiff
path: root/Tests/LibCrypto/TestBigInteger.cpp
diff options
context:
space:
mode:
authordavidot <davidot@serenityos.org>2022-08-25 23:37:09 +0200
committerLinus Groh <mail@linusgroh.de>2022-08-26 19:18:26 +0100
commit528891bf69f6d209b6884735fb6a47b17d1a81a7 (patch)
tree9718bd5407e9ef23e6d558c82e121734cbe89847 /Tests/LibCrypto/TestBigInteger.cpp
parentc87d10365bec1d5f7314e9333826039070e3f280 (diff)
downloadserenity-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.cpp74
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<>