summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fixed_point.h3
-rw-r--r--meson.build2
-rw-r--r--src/fixed_point.cpp9
-rw-r--r--tests/test_fixed_point.cpp20
4 files changed, 33 insertions, 1 deletions
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 <type_traits>
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);
+}