aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-02-19 21:36:19 +0100
committer hop311 <hop3114@gmail.com>2024-02-19 21:56:05 +0100
commite5a7ddfa0aeb8f62e2b53f111122c1c51c03dabc (patch)
treed55471ba1dd0a487e14e2ab18a3c4e3e2d0140ad /src/openvic-simulation
parent35e5f7828a41736194362186ad4f946fad5964d1 (diff)
Fixed point rounding functions and sources cleanup
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/testing/Requirement.cpp8
-rw-r--r--src/openvic-simulation/testing/Requirement.hpp12
-rw-r--r--src/openvic-simulation/testing/TestScript.cpp2
-rw-r--r--src/openvic-simulation/testing/TestScript.hpp4
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_001_file_tests.cpp3
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp3
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_003_military_unit_tests.cpp3
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_004_networking_tests.cpp3
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_005_nation_tests.cpp3
-rw-r--r--src/openvic-simulation/testing/test_scripts/A_006_politics_tests.cpp3
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPoint.hpp73
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPointLUT.hpp25
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp4
-rw-r--r--src/openvic-simulation/types/fixed_point/FixedPointMath.hpp11
-rw-r--r--src/openvic-simulation/types/fixed_point/lut_generator/lut_generator.py4
-rw-r--r--src/openvic-simulation/utility/Getters.hpp2
16 files changed, 88 insertions, 75 deletions
diff --git a/src/openvic-simulation/testing/Requirement.cpp b/src/openvic-simulation/testing/Requirement.cpp
index e7d03e5..eb48f5b 100644
--- a/src/openvic-simulation/testing/Requirement.cpp
+++ b/src/openvic-simulation/testing/Requirement.cpp
@@ -6,3 +6,11 @@ void Requirement::set_pass(bool in_pass) {
pass = in_pass;
set_tested(true); // Ever setting a pass condition implies it has been tested
}
+
+void Requirement::set_target_value(std::string_view new_target_value) {
+ target_value = new_target_value;
+}
+
+void Requirement::set_actual_value(std::string_view new_actual_value) {
+ actual_value = new_actual_value;
+}
diff --git a/src/openvic-simulation/testing/Requirement.hpp b/src/openvic-simulation/testing/Requirement.hpp
index e91fa79..85a1573 100644
--- a/src/openvic-simulation/testing/Requirement.hpp
+++ b/src/openvic-simulation/testing/Requirement.hpp
@@ -7,15 +7,15 @@ namespace OpenVic {
class Requirement {
// Loaded during construction
- std::string PROPERTY_RW(id);
- std::string PROPERTY_RW(text);
- std::string PROPERTY_RW(acceptance_criteria);
+ std::string PROPERTY(id);
+ std::string PROPERTY(text);
+ std::string PROPERTY(acceptance_criteria);
bool PROPERTY(pass);
bool PROPERTY_RW(tested);
// Initialised and used during script execution
- std::string PROPERTY_RW(target_value);
- std::string PROPERTY_RW(actual_value);
+ std::string PROPERTY(target_value);
+ std::string PROPERTY(actual_value);
public:
Requirement(std::string in_id, std::string in_text, std::string in_acceptance_criteria) {
@@ -27,5 +27,7 @@ namespace OpenVic {
}
void set_pass(bool in_pass);
+ void set_target_value(std::string_view new_target_value);
+ void set_actual_value(std::string_view new_actual_value);
};
}
diff --git a/src/openvic-simulation/testing/TestScript.cpp b/src/openvic-simulation/testing/TestScript.cpp
index ab0bfb9..13858fb 100644
--- a/src/openvic-simulation/testing/TestScript.cpp
+++ b/src/openvic-simulation/testing/TestScript.cpp
@@ -2,6 +2,8 @@
using namespace OpenVic;
+TestScript::TestScript(std::string_view new_script_name) : script_name { new_script_name } {}
+
// Getters
std::vector<Requirement*> TestScript::get_requirements() {
return requirements;
diff --git a/src/openvic-simulation/testing/TestScript.hpp b/src/openvic-simulation/testing/TestScript.hpp
index b41246e..fdf23a5 100644
--- a/src/openvic-simulation/testing/TestScript.hpp
+++ b/src/openvic-simulation/testing/TestScript.hpp
@@ -10,9 +10,11 @@ namespace OpenVic {
std::vector<Requirement*> requirements = std::vector<Requirement*>();
GameManager* PROPERTY_RW(game_manager);
- std::string PROPERTY_RW(script_name);
+ std::string PROPERTY(script_name);
public:
+ TestScript(std::string_view new_script_name);
+
// expects an overriden method that performs arbitrary code execution
// so that each script uniquely performs tests
// for both requirement adding to script and to execute code
diff --git a/src/openvic-simulation/testing/test_scripts/A_001_file_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_001_file_tests.cpp
index e24d44c..213da76 100644
--- a/src/openvic-simulation/testing/test_scripts/A_001_file_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_001_file_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_001_file_tests : public TestScript {
public:
- A_001_file_tests() {
- set_script_name("A_001_file_tests");
+ A_001_file_tests() : TestScript { "A_001_file_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp
index 4bff710..e811144 100644
--- a/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_002_economy_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_002_economy_tests : public TestScript {
public:
- A_002_economy_tests() {
- set_script_name("A_002_economy_tests");
+ A_002_economy_tests() : TestScript { "A_002_economy_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/testing/test_scripts/A_003_military_unit_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_003_military_unit_tests.cpp
index cf572d0..b61abb4 100644
--- a/src/openvic-simulation/testing/test_scripts/A_003_military_unit_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_003_military_unit_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_003_military_unit_tests : public TestScript {
public:
- A_003_military_unit_tests() {
- set_script_name("A_003_military_unit_tests");
+ A_003_military_unit_tests() : TestScript { "A_003_military_unit_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/testing/test_scripts/A_004_networking_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_004_networking_tests.cpp
index 0e05540..984a3c2 100644
--- a/src/openvic-simulation/testing/test_scripts/A_004_networking_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_004_networking_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_004_networking_tests : public TestScript {
public:
- A_004_networking_tests() {
- set_script_name("A_004_networking_tests");
+ A_004_networking_tests() : TestScript { "A_004_networking_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/testing/test_scripts/A_005_nation_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_005_nation_tests.cpp
index 6f91ac2..bfa8a59 100644
--- a/src/openvic-simulation/testing/test_scripts/A_005_nation_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_005_nation_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_005_nation_tests : public TestScript {
public:
- A_005_nation_tests() {
- set_script_name("A_005_nation_tests");
+ A_005_nation_tests() : TestScript { "A_005_nation_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/testing/test_scripts/A_006_politics_tests.cpp b/src/openvic-simulation/testing/test_scripts/A_006_politics_tests.cpp
index 091075c..f9e93d9 100644
--- a/src/openvic-simulation/testing/test_scripts/A_006_politics_tests.cpp
+++ b/src/openvic-simulation/testing/test_scripts/A_006_politics_tests.cpp
@@ -5,8 +5,7 @@ namespace OpenVic {
class A_006_politics_tests : public TestScript {
public:
- A_006_politics_tests() {
- set_script_name("A_006_politics_tests");
+ A_006_politics_tests() : TestScript { "A_006_politics_tests" } {
add_requirements();
}
diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
index 6a47194..95d2759 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp
@@ -6,7 +6,7 @@
#include <sstream>
#include <string_view>
-#include "openvic-simulation/types/fixed_point/FixedPointLUT.hpp"
+#include "openvic-simulation/utility/Getters.hpp"
#include "openvic-simulation/utility/Logger.hpp"
#include "openvic-simulation/utility/NumberUtils.hpp"
#include "openvic-simulation/utility/StringUtils.hpp"
@@ -18,14 +18,32 @@ namespace OpenVic {
static constexpr size_t SIZE = 8;
- static constexpr int32_t PRECISION = FPLUT::SIN_LUT_PRECISION;
+ static constexpr int32_t PRECISION = 16;
static constexpr int64_t ONE = 1 << PRECISION;
+ static constexpr int64_t FRAC_MASK = ONE - 1;
+ /* Fixed points represent any base 2 number with 48 bits above the point and 16 bits below it.
+ * - Any number expressible as n / 2^16 where n is an int64_t can be converted to a fixed point exactly.
+ * - If a number cannot be expressed as an integer divided by 2^16, it will be rounded down to the first
+ * representable number below it. For example: 0.01 = 655.36 / 2^16 becomes 0.0099945068359375 = 655 / 2^16.
+ * - While numbers with an integer part greater than 2^32 can be represented, they do not work properly with
+ * multiplication and division which involve an intermediate value that is 2^16 times larger than the result.
+ * For numbers with integer part smaller than 2^32 the top 16 bits prevent this intermediate value from
+ * overflowing. For larger values this will not work and the result will be missing its most significant bits. */
+
+ private:
+ int64_t PROPERTY_RW_CUSTOM_NAME(value, get_raw_value, set_raw_value);
+
+ /* Sin lookup table */
+ #include "openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp"
+
+ static_assert(SIN_LUT_PRECISION == PRECISION);
+
+ public:
constexpr fixed_point_t() : value { 0 } {}
constexpr fixed_point_t(int64_t new_value) : value { new_value } {}
constexpr fixed_point_t(int32_t new_value) : value { static_cast<int64_t>(new_value) << PRECISION } {}
- // Trivial destructor
constexpr ~fixed_point_t() = default;
static constexpr fixed_point_t max() {
@@ -200,6 +218,23 @@ namespace OpenVic {
return static_cast<int64_t>(178145LL);
}
+ constexpr fixed_point_t sin() const {
+ int64_t num = (*this % pi2() * one_div_pi2()).get_raw_value();
+
+ const bool negative = num < 0;
+ if (negative) {
+ num = -num;
+ }
+
+ const int64_t index = num >> SIN_LUT_SHIFT;
+ const int64_t a = SIN_LUT[index];
+ const int64_t b = SIN_LUT[index + 1];
+
+ const int64_t fraction = (num - (index << SIN_LUT_SHIFT)) << SIN_LUT_COUNT_LOG2;
+ const int64_t result = a + (((b - a) * fraction) >> SIN_LUT_PRECISION);
+ return !negative ? result : -result;
+ }
+
constexpr bool is_negative() const {
return value < 0;
}
@@ -216,23 +251,35 @@ namespace OpenVic {
// Doesn't account for sign, so -n.abc -> 1 - 0.abc
constexpr fixed_point_t get_frac() const {
- return value & (ONE - 1);
+ return value & FRAC_MASK;
}
constexpr bool is_integer() const {
return get_frac() == 0;
}
- constexpr int64_t to_int64_t() const {
- return value >> PRECISION;
+ constexpr fixed_point_t floor() const {
+ return value & ~FRAC_MASK;
}
- constexpr void set_raw_value(int64_t value) {
- this->value = value;
+ constexpr fixed_point_t ceil() const {
+ return floor() + !is_integer();
}
- constexpr int64_t get_raw_value() const {
- return value;
+ /* WARNING: the results of these rounding functions are affected by the accuracy of base 2 fixed point numbers,
+ * for example 1.0 rounded to a multiple of 0.01 is 0.99945068359375 for down and 1.0094451904296875 for up. */
+ constexpr fixed_point_t round_down_to_multiple(fixed_point_t factor) const {
+ const fixed_point_t remainder = *this % factor;
+ return *this - remainder - (remainder < 0 ? factor : _0());
+ }
+
+ constexpr fixed_point_t round_up_to_multiple(fixed_point_t factor) const {
+ const fixed_point_t remainder = *this % factor;
+ return *this - remainder + (remainder > 0 ? factor : _0());
+ }
+
+ constexpr int64_t to_int64_t() const {
+ return value >> PRECISION;
}
constexpr int32_t to_int32_t() const {
@@ -251,13 +298,13 @@ namespace OpenVic {
return value / static_cast<double>(ONE);
}
- constexpr float to_double_rounded() const {
+ constexpr double to_double_rounded() const {
return NumberUtils::round_to_int64((value / static_cast<double>(ONE)) * 100000.0) / 100000.0;
}
static std::ostream& print(std::ostream& stream, fixed_point_t val, size_t decimal_places = 0) {
if (decimal_places > 0) {
- fixed_point_t err = fixed_point_t::_0_50();
+ fixed_point_t err = _0_50();
for (size_t i = decimal_places; i > 0; --i) {
err /= 10;
}
@@ -612,8 +659,6 @@ namespace OpenVic {
}
private:
- int64_t value;
-
static constexpr fixed_point_t parse_integer(char const* str, char const* const end, bool* successful) {
int64_t parsed_value = StringUtils::string_to_int64(str, end, successful, 10);
return parse(parsed_value);
diff --git a/src/openvic-simulation/types/fixed_point/FixedPointLUT.hpp b/src/openvic-simulation/types/fixed_point/FixedPointLUT.hpp
deleted file mode 100644
index a5d585f..0000000
--- a/src/openvic-simulation/types/fixed_point/FixedPointLUT.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-namespace OpenVic::FPLUT {
-
-#include "openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp"
-
- constexpr int32_t SHIFT = SIN_LUT_PRECISION - SIN_LUT_COUNT_LOG2;
-
- constexpr int64_t sin(int64_t value) {
- int sign = 1;
- if (value < 0) {
- value = -value;
- sign = -1;
- }
-
- int index = value >> SHIFT;
- int64_t a = SIN_LUT[index];
- int64_t b = SIN_LUT[index + 1];
- int64_t fraction = (value - (index << SHIFT)) << SIN_LUT_COUNT_LOG2;
- int64_t result = a + (((b - a) * fraction) >> SIN_LUT_PRECISION);
- return result * sign;
- }
-}
diff --git a/src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp b/src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp
index 0c75efe..2b935a3 100644
--- a/src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp
+++ b/src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp
@@ -1,9 +1,7 @@
-#pragma once
-
-#include <cstdint>
static constexpr int32_t SIN_LUT_PRECISION = 16;
static constexpr int32_t SIN_LUT_COUNT_LOG2 = 9;
+static constexpr int32_t SIN_LUT_SHIFT = SIN_LUT_PRECISION - SIN_LUT_COUNT_LOG2;
static constexpr int64_t SIN_LUT[(1 << SIN_LUT_COUNT_LOG2) + 1] = {
0, 804, 1608, 2412, 3216, 4019, 4821, 5623, 6424, 7224, 8022, 8820, 9616, 10411, 11204, 11996,
diff --git a/src/openvic-simulation/types/fixed_point/FixedPointMath.hpp b/src/openvic-simulation/types/fixed_point/FixedPointMath.hpp
deleted file mode 100644
index 6cdb926..0000000
--- a/src/openvic-simulation/types/fixed_point/FixedPointMath.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
-
-namespace OpenVic::FPMath {
- constexpr fixed_point_t sin(fixed_point_t number) {
- number %= fixed_point_t::pi2();
- number *= fixed_point_t::one_div_pi2();
- return FPLUT::sin(number.get_raw_value());
- }
-}
diff --git a/src/openvic-simulation/types/fixed_point/lut_generator/lut_generator.py b/src/openvic-simulation/types/fixed_point/lut_generator/lut_generator.py
index 8ae7a32..e20eaa3 100644
--- a/src/openvic-simulation/types/fixed_point/lut_generator/lut_generator.py
+++ b/src/openvic-simulation/types/fixed_point/lut_generator/lut_generator.py
@@ -20,12 +20,10 @@ def generate_sin_lut(precision : int, count_log2 : int):
SinLut.append(SinLut[0])
output = [
- "#pragma once",
- "",
- "#include <cstdint>",
"",
f"static constexpr int32_t SIN_LUT_PRECISION = {precision};",
f"static constexpr int32_t SIN_LUT_COUNT_LOG2 = {count_log2};",
+ "static constexpr int32_t SIN_LUT_SHIFT = SIN_LUT_PRECISION - SIN_LUT_COUNT_LOG2;",
"",
"static constexpr int64_t SIN_LUT[(1 << SIN_LUT_COUNT_LOG2) + 1] = {"
]
diff --git a/src/openvic-simulation/utility/Getters.hpp b/src/openvic-simulation/utility/Getters.hpp
index fa76e74..0a6917c 100644
--- a/src/openvic-simulation/utility/Getters.hpp
+++ b/src/openvic-simulation/utility/Getters.hpp
@@ -121,7 +121,7 @@ ACCESS:
#define PROPERTY_RW_FULL(NAME, GETTER_NAME, SETTER_NAME, ACCESS) \
PROPERTY_FULL(NAME, GETTER_NAME, ACCESS) \
public: \
- void SETTER_NAME(decltype(NAME) new_##NAME) { \
+ constexpr void SETTER_NAME(decltype(NAME) new_##NAME) { \
NAME = new_##NAME; \
} \
ACCESS: