summaryrefslogtreecommitdiff
path: root/Tests
diff options
context:
space:
mode:
authordavidot <davidot@serenityos.org>2022-08-25 17:56:34 +0200
committerLinus Groh <mail@linusgroh.de>2022-08-26 19:18:26 +0100
commit77d71a5ffd784dd076c00454b59bcf674d747b69 (patch)
tree83dce04f6d6615745a9be5daf4e816e0d1482fc2 /Tests
parent8ba6e96d050881c0b77baf68d39bcba3de0d049b (diff)
downloadserenity-77d71a5ffd784dd076c00454b59bcf674d747b69.zip
LibCrypto: Add a rounding mode to UnsignedBigInteger::to_double
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.
Diffstat (limited to 'Tests')
-rw-r--r--Tests/LibCrypto/TestBigInteger.cpp38
1 files changed, 36 insertions, 2 deletions
diff --git a/Tests/LibCrypto/TestBigInteger.cpp b/Tests/LibCrypto/TestBigInteger.cpp
index 117f5e1891..3a94712739 100644
--- a/Tests/LibCrypto/TestBigInteger.cpp
+++ b/Tests/LibCrypto/TestBigInteger.cpp
@@ -750,7 +750,7 @@ EXPECT_EQUAL_TO(zero, -0.0);
TEST_CASE(to_double)
{
#define EXPECT_TO_EQUAL_DOUBLE(bigint, double_value) \
- EXPECT_EQ((bigint).to_double(), double_value)
+ EXPECT_EQ((bigint).to_double(Crypto::UnsignedBigInteger::RoundingMode::RoundTowardZero), double_value)
EXPECT_TO_EQUAL_DOUBLE(Crypto::UnsignedBigInteger(0), 0.0);
// Make sure we don't get negative zero!
@@ -825,7 +825,41 @@ TEST_CASE(to_double)
EXPECT_TO_EQUAL_DOUBLE(Crypto::SignedBigInteger::from_base(10, "2345678901234567890"sv),
2345678901234567680.0);
- EXPECT_EQ(1234567890123456800.0, 1234567890123456768.0);
+ EXPECT_EQ(
+ Crypto::UnsignedBigInteger::from_base(16, "1fffffffffffff00"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 2305843009213693696.0);
+
+ EXPECT_EQ(
+ Crypto::UnsignedBigInteger::from_base(16, "1fffffffffffff00"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::RoundTowardZero),
+ 2305843009213693696.0);
+
+ EXPECT_EQ(
+ Crypto::UnsignedBigInteger::from_base(16, "1fffffffffffff80"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 2305843009213693952.0);
+
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000001"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740992.0);
+
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000002"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740994.0);
+
+ // 2^53 = 20000000000000, +3 Rounds up because of tiesRoundToEven
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000003"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740996.0);
+
+ // +4 is exactly 9007199254740996
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000004"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740996.0);
+
+ // +5 rounds down because of tiesRoundToEven
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000005"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740996.0);
+
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(16, "20000000000006"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ 9007199254740998.0);
+
+ EXPECT_EQ(Crypto::UnsignedBigInteger::from_base(10, "98382635059784269824"sv).to_double(Crypto::UnsignedBigInteger::RoundingMode::IEEERoundAndTiesToEvenMantissa),
+ bit_cast<double>(0x4415555555555555ULL));
#undef EXPECT_TO_EQUAL_DOUBLE
}