From 7bb49794297b46aa1c577e89da24d39b4348c6d4 Mon Sep 17 00:00:00 2001 From: batsumaru <> Date: Sun, 9 Aug 2026 12:39:50 +0900 Subject: Added fp_t multiplication --- include/fixed_point.h | 3 +++ meson.build | 2 +- src/fixed_point.cpp | 9 +++++++++ tests/test_fixed_point.cpp | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/fixed_point.h b/include/fixed_point.h index 1bdc5df..ff8e2b3 100644 --- a/include/fixed_point.h +++ b/include/fixed_point.h @@ -5,6 +5,8 @@ #include struct fp_t { + static constexpr int32_t Q = 16; + static constexpr int32_t K = 1 << (Q - 1); std::int32_t raw; static constexpr fp_t from_raw(std::int32_t r) { return fp_t{r}; } @@ -12,6 +14,7 @@ struct fp_t { fp_t operator+(const fp_t& other) const; fp_t operator-(const fp_t& other) const; + fp_t operator*(const fp_t& other) const; bool operator==(const fp_t& other) const; }; diff --git a/meson.build b/meson.build index e5c654d..bff85ce 100644 --- a/meson.build +++ b/meson.build @@ -28,4 +28,4 @@ test_exe = executable('fg-tests', dependencies: [sim_core_dep, catch2_dep], ) -test('unit tests', test_exe) +test('unit tests', test_exe, args: ['-r', 'automake']) diff --git a/src/fixed_point.cpp b/src/fixed_point.cpp index 9b2d8e2..847a5f7 100644 --- a/src/fixed_point.cpp +++ b/src/fixed_point.cpp @@ -8,6 +8,15 @@ fp_t fp_t::operator-(const fp_t& other) const { return {(int32_t)((uint32_t)raw - (uint32_t)other.raw)}; } +fp_t fp_t::operator*(const fp_t& other) const { + int32_t result; + int64_t temp; + temp = (int64_t)raw * (int64_t)other.raw; + temp += fp_t::K; + result = (int32_t)(temp >> fp_t::Q); + return {result}; +} + bool fp_t::operator==(const fp_t& other) const { return raw == other.raw; } diff --git a/tests/test_fixed_point.cpp b/tests/test_fixed_point.cpp index b116340..6d1a594 100644 --- a/tests/test_fixed_point.cpp +++ b/tests/test_fixed_point.cpp @@ -17,6 +17,13 @@ TEST_CASE("fp_t subtraction anti-commutative") { REQUIRE(a.raw != 0); } +TEST_CASE("fp_t multiplication is commutative") { + fp_t a = fp_t::from_int(2); + fp_t b = fp_t::from_int(5); + CHECK(a * b == b * a); + REQUIRE(a.raw != 1); +} + TEST_CASE("fp_t addition overflows") { fp_t a = fp_t::from_raw(INT32_MAX); fp_t b = fp_t::from_raw(1); @@ -30,3 +37,16 @@ TEST_CASE("fp_t subtraction underflows") { fp_t c = fp_t::from_raw(INT32_MAX); CHECK(a - b == c); } + +TEST_CASE("fp_t multiplication overflows") { + fp_t a = fp_t::from_raw(INT32_MAX); + fp_t b = fp_t::from_int(2); + fp_t c = fp_t::from_raw(-2); + CHECK(a * b == c); +} + +TEST_CASE("fp_t multiplication drops percision under 1 ULP") { + fp_t a = fp_t::from_raw(1); + fp_t b = fp_t::from_raw(0); + CHECK(a * a == b); +} -- cgit v1.3