From 2696740c01ba934de31cb83e3e8166f4e17dcd15 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Mon, 5 Jul 2021 17:37:26 +0200 Subject: [PATCH] math: add rounding-conversion functions for rationals --- src/common/math_fwd.h | 12 ++++++++++++ tests/unit/common/math.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/common/math_fwd.h b/src/common/math_fwd.h index 3cf73b8e8..c69fb81a7 100644 --- a/src/common/math_fwd.h +++ b/src/common/math_fwd.h @@ -47,6 +47,18 @@ to_uint(mtx_mp_rational_t const &value) { return static_cast(static_cast(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((static_cast(value * 10 + shift)) / 10); +} + +inline uint64_t +to_uint_rounded(mtx_mp_rational_t const &value) { + return static_cast((static_cast(value * 10 + 5)) / 10); +} + namespace math { } diff --git a/tests/unit/common/math.cpp b/tests/unit/common/math.cpp index 3afab332d..6b51dd794 100644 --- a/tests/unit/common/math.cpp +++ b/tests/unit/common/math.cpp @@ -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); +} + }