From 60d3b5bdde3f0c4001fa8c4843f999e77568f810 Mon Sep 17 00:00:00 2001 From: hop311 Date: Mon, 18 Mar 2024 19:58:00 +0000 Subject: Add fixed_point_map_t operators and helper functions --- .../types/fixed_point/FixedPoint.hpp | 4 + .../types/fixed_point/FixedPointMap.hpp | 128 ++++++++++++++++++++- 2 files changed, 129 insertions(+), 3 deletions(-) diff --git a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp index 95d2759..9ad7966 100644 --- a/src/openvic-simulation/types/fixed_point/FixedPoint.hpp +++ b/src/openvic-simulation/types/fixed_point/FixedPoint.hpp @@ -658,6 +658,10 @@ namespace OpenVic { return static_cast(lhs) << PRECISION != rhs.value; } + constexpr friend std::strong_ordering operator<=>(fixed_point_t const& lhs, fixed_point_t const& rhs) { + return lhs.value <=> rhs.value; + } + private: 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); diff --git a/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp index 1904fec..5df537a 100644 --- a/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp +++ b/src/openvic-simulation/types/fixed_point/FixedPointMap.hpp @@ -14,20 +14,140 @@ namespace OpenVic { template using fixed_point_map_const_iterator_t = typename fixed_point_map_t::const_iterator; + template U> + constexpr fixed_point_map_t& cast_map(fixed_point_map_t& map) { + return *reinterpret_cast*>(&map); + } + + template U> + constexpr fixed_point_map_t const& cast_map(fixed_point_map_t const& map) { + return *reinterpret_cast const*>(&map); + } + + template + constexpr fixed_point_map_t& operator+=(fixed_point_map_t& lhs, fixed_point_map_t const& rhs) { + for (auto const& [key, value] : rhs) { + lhs[key] += value; + } + + return lhs; + } + + template + constexpr fixed_point_map_t operator+(fixed_point_map_t const& lhs, fixed_point_map_t const& rhs) { + fixed_point_map_t result = lhs; + + result += rhs; + + return result; + } + + template + constexpr fixed_point_map_t& operator*=(fixed_point_map_t& lhs, fixed_point_t rhs) { + for (auto [key, value] : mutable_iterator(lhs)) { + value *= rhs; + } + + return lhs; + } + + template + constexpr fixed_point_map_t operator*(fixed_point_map_t const& lhs, fixed_point_t rhs) { + fixed_point_map_t result = lhs; + + result *= rhs; + + return result; + } + + template + constexpr fixed_point_map_t operator*(fixed_point_t lhs, fixed_point_map_t const& rhs) { + return rhs * lhs; + } + + template + constexpr fixed_point_map_t& operator/=(fixed_point_map_t& lhs, fixed_point_t rhs) { + for (auto [key, value] : mutable_iterator(lhs)) { + value /= rhs; + } + + return lhs; + } + + template + constexpr fixed_point_map_t operator/(fixed_point_map_t const& lhs, fixed_point_t rhs) { + fixed_point_map_t result = lhs; + + result /= rhs; + + return result; + } + + /* Assumes arguments are sorted with keys ascending. Result is determined by the + * first non-equal keys or values found starting from the back of the maps. */ + template + constexpr bool sorted_fixed_map_less_than(fixed_point_map_t const& lhs, fixed_point_map_t const& rhs) { + + typename fixed_point_map_t::const_reverse_iterator lit, rit; + + for (lit = lhs.rcbegin(), rit = rhs.rcbegin(); lit != lhs.rcend() && rit != rhs.rcend(); lit++, rit++) { + + const std::strong_ordering key_cmp = lit->first <=> rit->first; + + if (key_cmp != std::strong_ordering::equal) { + return key_cmp == std::strong_ordering::less; + } + + const std::strong_ordering value_cmp = lit->second <=> rit->second; + + if (value_cmp != std::strong_ordering::equal) { + return value_cmp == std::strong_ordering::less; + } + + } + + return rit != rhs.rcend(); + } + template constexpr fixed_point_t get_total(fixed_point_map_t const& map) { fixed_point_t total = 0; + for (auto const& [key, value] : map) { total += value; } + return total; } + template + constexpr void normalise_fixed_point_map(fixed_point_map_t& map) { + const fixed_point_t total = get_total(map); + + if (total > 0) { + map /= total; + } + } + + template + constexpr void rescale_fixed_point_map(fixed_point_map_t& map, fixed_point_t new_total) { + const fixed_point_t total = get_total(map); + + if (total > 0) { + for (auto [key, value] : mutable_iterator(map)) { + value *= new_total; + value /= total; + } + } + } + template constexpr fixed_point_map_const_iterator_t get_largest_item(fixed_point_map_t const& map) { - constexpr auto pred = [](fixed_point_map_value_t a, fixed_point_map_value_t b) -> bool { - return a.second < b.second; - }; + constexpr auto pred = + [](fixed_point_map_value_t const& lhs, fixed_point_map_value_t const& rhs) -> bool { + return lhs.second < rhs.second; + }; + return std::max_element(map.begin(), map.end(), pred); } @@ -36,6 +156,7 @@ namespace OpenVic { fixed_point_map_t const& map ) { fixed_point_map_const_iterator_t largest = map.end(), second_largest = map.end(); + for (fixed_point_map_const_iterator_t it = map.begin(); it != map.end(); ++it) { if (largest == map.end() || it->second > largest->second) { second_largest = largest; @@ -44,6 +165,7 @@ namespace OpenVic { second_largest = it; } } + return std::make_pair(std::move(largest), std::move(second_largest)); } } -- cgit v1.2.3-56-ga3b1