math: add rounding-conversion functions for rationals

This commit is contained in:
Moritz Bunkus 2021-07-05 17:37:26 +02:00
parent 6d0758a74a
commit 2696740c01
No known key found for this signature in database
GPG Key ID: 74AF00ADF2E32C85
2 changed files with 46 additions and 0 deletions

View File

@ -47,6 +47,18 @@ to_uint(mtx_mp_rational_t const &value) {
return static_cast<uint64_t>(static_cast<boost::multiprecision::uint128_t>(value));
}
// Additional conversions that round to the nearest integer away from 0.
inline int64_t
to_int_rounded(mtx_mp_rational_t const &value) {
auto shift = value >= 0 ? 5 : -5;
return static_cast<int64_t>((static_cast<boost::multiprecision::int128_t>(value * 10 + shift)) / 10);
}
inline uint64_t
to_uint_rounded(mtx_mp_rational_t const &value) {
return static_cast<uint64_t>((static_cast<boost::multiprecision::uint128_t>(value * 10 + 5)) / 10);
}
namespace math {
}

View File

@ -74,4 +74,38 @@ TEST(Math, ClampValueTo) {
EXPECT_EQ((mtx_mp_rational_t{65'535, 1}), mtx::math::clamp_values_to({999'999'999, 1}, 65535));
}
TEST(Math, ToIntTruncating) {
EXPECT_EQ(mtx::to_int(mtx::rational(-0, 3)), -0);
EXPECT_EQ(mtx::to_int(mtx::rational(-1, 3)), -0);
EXPECT_EQ(mtx::to_int(mtx::rational(-2, 3)), -0);
EXPECT_EQ(mtx::to_int(mtx::rational(-3, 3)), -1);
EXPECT_EQ(mtx::to_int(mtx::rational(0, 3)), 0);
EXPECT_EQ(mtx::to_int(mtx::rational(1, 3)), 0);
EXPECT_EQ(mtx::to_int(mtx::rational(2, 3)), 0);
EXPECT_EQ(mtx::to_int(mtx::rational(3, 3)), 1);
EXPECT_EQ(mtx::to_uint(mtx::rational(0, 3)), 0);
EXPECT_EQ(mtx::to_uint(mtx::rational(1, 3)), 0);
EXPECT_EQ(mtx::to_uint(mtx::rational(2, 3)), 0);
EXPECT_EQ(mtx::to_uint(mtx::rational(3, 3)), 1);
}
TEST(Math, ToIntRounding) {
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(-0, 3)), -0);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(-1, 3)), -0);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(-2, 3)), -1);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(-3, 3)), -1);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(0, 3)), 0);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(1, 3)), 0);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(2, 3)), 1);
EXPECT_EQ(mtx::to_int_rounded(mtx::rational(3, 3)), 1);
EXPECT_EQ(mtx::to_uint_rounded(mtx::rational(0, 3)), 0);
EXPECT_EQ(mtx::to_uint_rounded(mtx::rational(1, 3)), 0);
EXPECT_EQ(mtx::to_uint_rounded(mtx::rational(2, 3)), 1);
EXPECT_EQ(mtx::to_uint_rounded(mtx::rational(3, 3)), 1);
}
}