From 366f1b3941315641bdcb0ee98465b4d2134eee86 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Fri, 25 Aug 2023 23:25:12 +0100 Subject: Followup big dataloader commit --- src/openvic/types/Date.cpp | 122 ++++++++++++-------- src/openvic/types/Date.hpp | 8 +- src/openvic/types/IdentifierRegistry.cpp | 8 ++ src/openvic/types/IdentifierRegistry.hpp | 18 ++- src/openvic/types/fixed_point/FP.hpp | 192 +++++++++++++++++-------------- 5 files changed, 207 insertions(+), 141 deletions(-) (limited to 'src/openvic/types') diff --git a/src/openvic/types/Date.cpp b/src/openvic/types/Date.cpp index b6e1367..1f13808 100644 --- a/src/openvic/types/Date.cpp +++ b/src/openvic/types/Date.cpp @@ -6,6 +6,7 @@ #include #include "openvic/utility/Logger.hpp" +#include "openvic/utility/StringUtils.hpp" using namespace OpenVic; @@ -55,12 +56,16 @@ Timespan::operator double() const { return days; } -Timespan::operator std::string() const { +std::string Timespan::to_string() const { return std::to_string(days); } +Timespan::operator std::string() const { + return to_string(); +} + std::ostream& OpenVic::operator<<(std::ostream& out, Timespan const& timespan) { - return out << static_cast(timespan); + return out << timespan.to_string(); } Timespan Date::_dateToTimespan(year_t year, month_t month, day_t day) { @@ -146,95 +151,112 @@ Date Date::operator++(int) { return old; } -Date::operator std::string() const { +std::string Date::to_string() const { std::stringstream ss; ss << *this; return ss.str(); } +Date::operator std::string() const { + return to_string(); +} + std::ostream& OpenVic::operator<<(std::ostream& out, Date const& date) { - return out << static_cast(date.getYear()) << '.' << static_cast(date.getMonth()) << '.' << static_cast(date.getDay()); + return out << static_cast(date.getYear()) << Date::SEPARATOR_CHARACTER << static_cast(date.getMonth()) << Date::SEPARATOR_CHARACTER << static_cast(date.getDay()); } // Parsed from string of the form YYYY.MM.DD -Date Date::from_string(const std::string_view date, bool* successful) { +Date Date::from_string(char const* const str, char const* const end, bool* successful) { if (successful != nullptr) *successful = true; - size_t first_pos = 0; - while (first_pos < date.length() && std::isdigit(date[first_pos])) { - first_pos++; + + year_t year = 0; + month_t month = 1; + day_t day = 1; + + if (str == nullptr || end <= str) { + Logger::error("Invalid string start/end pointers: ", static_cast(str), " - ", static_cast(end)); + if (successful != nullptr) *successful = false; + return { year, month, day }; } - if (first_pos == 0) { - Logger::error("Failed to find year digits in date: ", date); + char const* year_end = str; + while (std::isdigit(*year_end) && ++year_end < end); + + if (year_end <= str) { + Logger::error("Failed to find year digits in date: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; - return {}; + return { year, month, day }; } - int val = 0; - char const* start = date.data(); - char const* end = start + first_pos; - std::from_chars_result result = std::from_chars(start, end, val); - if (result.ec != std::errc{} || result.ptr != end || val < 0 || val >= 1 << (8 * sizeof(year_t))) { - Logger::error("Failed to read year: ", date); + bool sub_successful = false; + uint64_t val = StringUtils::string_to_uint64(str, year_end, &sub_successful, 10); + if (!sub_successful || val >= 1 << (8 * sizeof(year_t))) { + Logger::error("Failed to read year: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; - return {}; + return { year, month, day }; } - year_t year = val; - month_t month = 1; - day_t day = 1; - if (first_pos < date.length()) { - if (date[first_pos] == '.') { - size_t second_pos = ++first_pos; - while (second_pos < date.length() && std::isdigit(date[second_pos])) { - second_pos++; + year = val; + if (year_end < end) { + if (*year_end == SEPARATOR_CHARACTER) { + char const* const month_start = year_end + 1; + char const* month_end = month_start; + if (month_start < end) { + while (std::isdigit(*month_end) && ++month_end < end); } - if (first_pos == second_pos) { - Logger::error("Failed to find month digits in date: ", date); + if (month_start >= month_end) { + Logger::error("Failed to find month digits in date: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } else { - start = date.data() + first_pos; - end = date.data() + second_pos; - result = std::from_chars(start, end, val); - if (result.ec != std::errc{} || result.ptr != end || val < 1 || val > MONTHS_IN_YEAR) { - Logger::error("Failed to read month: ", date); + sub_successful = false; + val = StringUtils::string_to_uint64(month_start, month_end, &sub_successful, 10); + if (!sub_successful || val < 1 || val > MONTHS_IN_YEAR) { + Logger::error("Failed to read month: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } else { month = val; - if (second_pos < date.length()) { - if (date[second_pos] == '.') { - size_t third_pos = ++second_pos; - while (third_pos < date.length() && std::isdigit(date[third_pos])) { - third_pos++; + if (month_end < end) { + if (*month_end == SEPARATOR_CHARACTER) { + char const* const day_start = month_end + 1; + char const* day_end = day_start; + if (day_start < end) { + while (std::isdigit(*day_end) && ++day_end < end); } - if (second_pos == third_pos) { - Logger::error("Failed to find day digits in date: ", date); + if (day_start >= day_end) { + Logger::error("Failed to find day digits in date: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } else { - start = date.data() + second_pos; - end = date.data() + third_pos; - result = std::from_chars(start, end, val); - if (result.ec != std::errc{} || result.ptr != end || val < 1 || val > DAYS_IN_MONTH[month - 1]) { - Logger::error("Failed to read day: ", date); + sub_successful = false; + val = StringUtils::string_to_uint64(day_start, day_end, &sub_successful); + if (!sub_successful || val < 1 || val > DAYS_IN_MONTH[month - 1]) { + Logger::error("Failed to read day: ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } else { day = val; - if (third_pos < date.length()) { - Logger::error("Unexpected string \"", date.substr(third_pos), "\" at the end of date ", date); + if (day_end < end) { + Logger::error("Unexpected string \"", std::string_view { day_end, static_cast(end - day_end) }, "\" at the end of date ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } } } } else { - Logger::error("Unexpected character \"", date[second_pos], "\" in month of date ", date); + Logger::error("Unexpected character \"", *month_end, "\" in month of date ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } } } } } else { - Logger::error("Unexpected character \"", date[first_pos], "\" in year of date ", date); + Logger::error("Unexpected character \"", *year_end, "\" in year of date ", std::string_view { str, static_cast(end - str) }); if (successful != nullptr) *successful = false; } } - return _dateToTimespan(year, month, day); + return { year, month, day }; }; + +Date Date::from_string(char const* str, size_t length, bool* successful) { + return from_string(str, str + length, successful); +} + +Date Date::from_string(const std::string_view str, bool* successful) { + return from_string(str.data(), str.length(), successful); +} diff --git a/src/openvic/types/Date.hpp b/src/openvic/types/Date.hpp index ca5645c..601f9dc 100644 --- a/src/openvic/types/Date.hpp +++ b/src/openvic/types/Date.hpp @@ -33,6 +33,7 @@ namespace OpenVic { explicit operator day_t() const; explicit operator double() const; + std::string to_string() const; explicit operator std::string() const; }; std::ostream& operator<<(std::ostream& out, Timespan const& timespan); @@ -50,6 +51,8 @@ namespace OpenVic { static Timespan::day_t const* DAYS_UP_TO_MONTH; static month_t const* MONTH_FROM_DAY_IN_YEAR; + static constexpr char SEPARATOR_CHARACTER = '.'; + private: // Number of days since Jan 1st, Year 0 Timespan timespan; @@ -82,9 +85,12 @@ namespace OpenVic { Date& operator++(); Date operator++(int); + std::string to_string() const; explicit operator std::string() const; // Parsed from string of the form YYYY.MM.DD - static Date from_string(const std::string_view date, bool* successful = nullptr); + static Date from_string(char const* str, char const* end, bool* successful = nullptr); + static Date from_string(char const* str, size_t length, bool* successful = nullptr); + static Date from_string(const std::string_view str, bool* successful = nullptr); }; std::ostream& operator<<(std::ostream& out, Date const& date); } diff --git a/src/openvic/types/IdentifierRegistry.cpp b/src/openvic/types/IdentifierRegistry.cpp index 97a1ff5..3710387 100644 --- a/src/openvic/types/IdentifierRegistry.cpp +++ b/src/openvic/types/IdentifierRegistry.cpp @@ -35,3 +35,11 @@ HasIdentifierAndColour::HasIdentifierAndColour(const std::string_view new_identi const colour_t new_colour, bool can_be_null) : HasIdentifier { new_identifier }, HasColour { new_colour, can_be_null } {} + +distribution_t::value_type OpenVic::get_largest_item(distribution_t const& dist) { + const distribution_t::const_iterator result = std::max_element(dist.begin(), dist.end(), + [](distribution_t::value_type a, distribution_t::value_type b) -> bool { + return a.second < b.second; + }); + return result != dist.end() ? *result : distribution_t::value_type { nullptr, -1.0f }; +} diff --git a/src/openvic/types/IdentifierRegistry.hpp b/src/openvic/types/IdentifierRegistry.hpp index e5ac94b..989db01 100644 --- a/src/openvic/types/IdentifierRegistry.hpp +++ b/src/openvic/types/IdentifierRegistry.hpp @@ -64,7 +64,9 @@ namespace OpenVic { HasIdentifierAndColour& operator=(HasIdentifierAndColour&&) = delete; }; - using distribution_t = std::unordered_map; + using distribution_t = std::map; + + distribution_t::value_type get_largest_item(distribution_t const& dist); /* * Template for a list of objects with unique string identifiers that can @@ -102,7 +104,7 @@ namespace OpenVic { Logger::error("Failed to lock ", name, " registry - already locked!"); } else { locked = true; - if (log) Logger::info("Locked ", name, " registry after registering ", get_item_count(), " items"); + if (log) Logger::info("Locked ", name, " registry after registering ", size(), " items"); } } bool is_locked() const { @@ -113,9 +115,19 @@ namespace OpenVic { items.clear(); locked = false; } - size_t get_item_count() const { + size_t size() const { return items.size(); } + bool empty() const { + return items.empty(); + } + void reserve(size_t size) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!"); + } else { + items.reserve(size); + } + } T* get_item_by_identifier(const std::string_view identifier) { const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier); if (it != identifier_index_map.end()) return &items[it->second]; diff --git a/src/openvic/types/fixed_point/FP.hpp b/src/openvic/types/fixed_point/FP.hpp index 8b32906..42ddf79 100644 --- a/src/openvic/types/fixed_point/FP.hpp +++ b/src/openvic/types/fixed_point/FP.hpp @@ -1,16 +1,17 @@ #pragma once -#include -#include #include #include +#include +#include #include -#include +#include -#include "FPLUT.hpp" -#include "openvic/utility/FloatUtils.hpp" -#include "openvic/utility/StringUtils.hpp" #include "openvic/utility/Logger.hpp" +#include "openvic/utility/NumberUtils.hpp" +#include "openvic/utility/StringUtils.hpp" + +#include "FPLUT.hpp" namespace OpenVic { struct FP { @@ -41,7 +42,7 @@ namespace OpenVic { static constexpr FP _0() { return 0; - } + } static constexpr FP _1() { return 1; @@ -195,13 +196,17 @@ namespace OpenVic { return static_cast(178145LL); } + constexpr bool is_negative() const { + return value < 0; + } + constexpr FP abs() const { - return value >= 0 ? value : -value; + return !is_negative() ? value : -value; } - // Not including sign, so -1.1 -> 0.1 + // Doesn't account for sign, so -n.abc -> 1 - 0.abc constexpr FP get_frac() const { - return abs().value & ((1 << FPLUT::PRECISION) - 1); + return value & (FPLUT::ONE - 1); } constexpr int64_t to_int64_t() const { @@ -217,33 +222,35 @@ namespace OpenVic { } constexpr int32_t to_int32_t() const { - return static_cast(value >> FPLUT::PRECISION); + return static_cast(to_int64_t()); } constexpr float to_float() const { - return value / 65536.0F; + return value / static_cast(FPLUT::ONE); } constexpr float to_float_rounded() const { - return static_cast(FloatUtils::round_to_int64((value / 65536.0F) * 100000.0F)) / 100000.0F; + return static_cast(NumberUtils::round_to_int64((value / static_cast(FPLUT::ONE)) * 100000.0f)) / 100000.0f; } - constexpr float to_double() const { - return value / 65536.0; + constexpr double to_double() const { + return value / static_cast(FPLUT::ONE); } constexpr float to_double_rounded() const { - return FloatUtils::round_to_int64((value / 65536.0) * 100000.0) / 100000.0; + return NumberUtils::round_to_int64((value / static_cast(FPLUT::ONE)) * 100000.0) / 100000.0; } std::string to_string() const { - std::string str = std::to_string(to_int64_t()) + "."; - FP frac_part = get_frac(); + FP val = abs(); + std::string str = std::to_string(val.to_int64_t()) + "."; + if (is_negative()) str = "-" + str; + val = val.get_frac(); do { - frac_part.value *= 10; - str += std::to_string(frac_part.to_int64_t()); - frac_part = frac_part.get_frac(); - } while (frac_part > 0); + val *= 10; + str.push_back('0' + static_cast(val.to_int64_t())); + val = val.get_frac(); + } while (val > 0); return str; } @@ -258,7 +265,7 @@ namespace OpenVic { } // Deterministic - static constexpr FP parse(const char* str, const char* end, bool *successful = nullptr) { + static constexpr FP parse(char const* str, char const* const end, bool* successful = nullptr) { if (successful != nullptr) *successful = false; if (str == nullptr || str >= end) { @@ -273,7 +280,7 @@ namespace OpenVic { if (str == end) return _0(); } - const char* dot_pointer = str; + char const* dot_pointer = str; while (*dot_pointer != '.' && ++dot_pointer != end); if (dot_pointer == str && dot_pointer + 1 == end) { @@ -287,31 +294,35 @@ namespace OpenVic { if (dot_pointer != str) { // Non-empty integer part bool int_successful = false; - result += parse_integer(str, dot_pointer, &int_successful); + result += parse_integer(str, dot_pointer, &int_successful); if (!int_successful && successful != nullptr) *successful = false; } if (dot_pointer + 1 < end) { // Non-empty fractional part bool frac_successful = false; - result += parse_fraction(dot_pointer + 1, end, &frac_successful); + result += parse_fraction(dot_pointer + 1, end, &frac_successful); if (!frac_successful && successful != nullptr) *successful = false; } return negative ? -result : result; } - static constexpr FP parse(const char* str, size_t length, bool *successful = nullptr) { + static constexpr FP parse(char const* str, size_t length, bool* successful = nullptr) { return parse(str, str + length, successful); } + static FP parse(const std::string_view str, bool* successful = nullptr) { + return parse(str.data(), str.length(), successful); + } + // Not Deterministic static constexpr FP parse_unsafe(float value) { return static_cast(value * FPLUT::ONE + 0.5f * (value < 0 ? -1 : 1)); } // Not Deterministic - static FP parse_unsafe(const char* value) { + static FP parse_unsafe(char const* value) { char* endpointer; double double_value = std::strtod(value, &endpointer); @@ -325,7 +336,7 @@ namespace OpenVic { } constexpr operator int32_t() const { - return to_int32_t(); + return to_int32_t(); } constexpr operator int64_t() const { @@ -344,218 +355,225 @@ namespace OpenVic { return to_string(); } - friend std::ostream& operator<<(std::ostream& stream, const FP& obj) { + friend std::ostream& operator<<(std::ostream& stream, FP const& obj) { return stream << obj.to_string(); } - constexpr friend FP operator-(const FP& obj) { + constexpr friend FP operator-(FP const& obj) { return -obj.value; } - constexpr friend FP operator+(const FP& obj) { + constexpr friend FP operator+(FP const& obj) { return +obj.value; } - constexpr friend FP operator+(const FP& lhs, const FP& rhs) { + constexpr friend FP operator+(FP const& lhs, FP const& rhs) { return lhs.value + rhs.value; } - constexpr friend FP operator+(const FP& lhs, const int32_t& rhs) { + constexpr friend FP operator+(FP const& lhs, int32_t const& rhs) { return lhs.value + (static_cast(rhs) << FPLUT::PRECISION); } - constexpr friend FP operator+(const int32_t& lhs, const FP& rhs) { + constexpr friend FP operator+(int32_t const& lhs, FP const& rhs) { return (static_cast(lhs) << FPLUT::PRECISION) + rhs.value; } - constexpr FP operator+=(const FP& obj) { + constexpr FP operator+=(FP const& obj) { value += obj.value; return *this; } - constexpr FP operator+=(const int32_t& obj) { + constexpr FP operator+=(int32_t const& obj) { value += (static_cast(obj) << FPLUT::PRECISION); return *this; } - constexpr friend FP operator-(const FP& lhs, const FP& rhs) { + constexpr friend FP operator-(FP const& lhs, FP const& rhs) { return lhs.value - rhs.value; } - constexpr friend FP operator-(const FP& lhs, const int32_t& rhs) { + constexpr friend FP operator-(FP const& lhs, int32_t const& rhs) { return lhs.value - (static_cast(rhs) << FPLUT::PRECISION); } - constexpr friend FP operator-(const int32_t& lhs, const FP& rhs) { + constexpr friend FP operator-(int32_t const& lhs, FP const& rhs) { return (static_cast(lhs) << FPLUT::PRECISION) - rhs.value; } - constexpr FP operator-=(const FP& obj) { + constexpr FP operator-=(FP const& obj) { value -= obj.value; return *this; } - constexpr FP operator-=(const int32_t& obj) { + constexpr FP operator-=(int32_t const& obj) { value -= (static_cast(obj) << FPLUT::PRECISION); return *this; } - constexpr friend FP operator*(const FP& lhs, const FP& rhs) { + constexpr friend FP operator*(FP const& lhs, FP const& rhs) { return lhs.value * rhs.value >> FPLUT::PRECISION; } - constexpr friend FP operator*(const FP& lhs, const int32_t& rhs) { + constexpr friend FP operator*(FP const& lhs, int32_t const& rhs) { return lhs.value * rhs; } - constexpr friend FP operator*(const int32_t& lhs, const FP& rhs) { + constexpr friend FP operator*(int32_t const& lhs, FP const& rhs) { return lhs * rhs.value; } - constexpr FP operator*=(const FP& obj) { + constexpr FP operator*=(FP const& obj) { value *= obj.value >> FPLUT::PRECISION; return *this; } - constexpr FP operator*=(const int32_t& obj) { + constexpr FP operator*=(int32_t const& obj) { value *= obj; return *this; } - constexpr friend FP operator/(const FP& lhs, const FP& rhs) { - return (lhs.value << FPLUT::PRECISION) / rhs.value; + constexpr friend FP operator/(FP const& lhs, FP const& rhs) { + return (lhs.value << FPLUT::PRECISION) / rhs.value; } - constexpr friend FP operator/(const FP& lhs, const int32_t& rhs) { + constexpr friend FP operator/(FP const& lhs, int32_t const& rhs) { return lhs.value / rhs; } - constexpr friend FP operator/(const int32_t& lhs, const FP& rhs) { - return (static_cast(lhs) << (2 / FPLUT::PRECISION)) / rhs.value; + constexpr friend FP operator/(int32_t const& lhs, FP const& rhs) { + return (static_cast(lhs) << (2 * FPLUT::PRECISION)) / rhs.value; } - constexpr FP operator/=(const FP& obj) { + constexpr FP operator/=(FP const& obj) { value = (value << FPLUT::PRECISION) / obj.value; return *this; } - constexpr FP operator/=(const int32_t& obj) { + constexpr FP operator/=(int32_t const& obj) { value /= obj; return *this; } - constexpr friend FP operator%(const FP& lhs, const FP& rhs) { + constexpr friend FP operator%(FP const& lhs, FP const& rhs) { return lhs.value % rhs.value; } - constexpr friend FP operator%(const FP& lhs, const int32_t& rhs) { + constexpr friend FP operator%(FP const& lhs, int32_t const& rhs) { return lhs.value % (static_cast(rhs) << FPLUT::PRECISION); } - constexpr friend FP operator%(const int32_t& lhs, const FP& rhs) { + constexpr friend FP operator%(int32_t const& lhs, FP const& rhs) { return (static_cast(lhs) << FPLUT::PRECISION) % rhs.value; } - constexpr FP operator%=(const FP& obj) { + constexpr FP operator%=(FP const& obj) { value %= obj.value; return *this; } - constexpr FP operator%=(const int32_t& obj) { + constexpr FP operator%=(int32_t const& obj) { value %= (static_cast(obj) << FPLUT::PRECISION); return *this; } - constexpr friend bool operator<(const FP& lhs, const FP& rhs) { + constexpr friend bool operator<(FP const& lhs, FP const& rhs) { return lhs.value < rhs.value; } - constexpr friend bool operator<(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator<(FP const& lhs, int32_t const& rhs) { return lhs.value < static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator<(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator<(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION < rhs.value; } - constexpr friend bool operator<=(const FP& lhs, const FP& rhs) { + constexpr friend bool operator<=(FP const& lhs, FP const& rhs) { return lhs.value <= rhs.value; } - constexpr friend bool operator<=(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator<=(FP const& lhs, int32_t const& rhs) { return lhs.value <= static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator<=(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator<=(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION <= rhs.value; } - constexpr friend bool operator>(const FP& lhs, const FP& rhs) { + constexpr friend bool operator>(FP const& lhs, FP const& rhs) { return lhs.value > rhs.value; } - constexpr friend bool operator>(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator>(FP const& lhs, int32_t const& rhs) { return lhs.value > static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator>(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator>(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION > rhs.value; } - constexpr friend bool operator>=(const FP& lhs, const FP& rhs) { + constexpr friend bool operator>=(FP const& lhs, FP const& rhs) { return lhs.value >= rhs.value; } - constexpr friend bool operator>=(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator>=(FP const& lhs, int32_t const& rhs) { return lhs.value >= static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator>=(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator>=(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION >= rhs.value; } - constexpr friend bool operator==(const FP& lhs, const FP& rhs) { + constexpr friend bool operator==(FP const& lhs, FP const& rhs) { return lhs.value == rhs.value; } - constexpr friend bool operator==(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator==(FP const& lhs, int32_t const& rhs) { return lhs.value == static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator==(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator==(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION == rhs.value; } - constexpr friend bool operator!=(const FP& lhs, const FP& rhs) { + constexpr friend bool operator!=(FP const& lhs, FP const& rhs) { return lhs.value != rhs.value; } - constexpr friend bool operator!=(const FP& lhs, const int32_t& rhs) { + constexpr friend bool operator!=(FP const& lhs, int32_t const& rhs) { return lhs.value != static_cast(rhs) << FPLUT::PRECISION; } - constexpr friend bool operator!=(const int32_t& lhs, const FP& rhs) { + constexpr friend bool operator!=(int32_t const& lhs, FP const& rhs) { return static_cast(lhs) << FPLUT::PRECISION != rhs.value; } - private: int64_t value; - static constexpr FP parse_integer(const char* str, const char* end, bool* successful) { + static constexpr FP 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); } - static constexpr FP parse_fraction(const char* str, const char* end, bool* successful) { - constexpr size_t READ_SIZE = 5; - if (str + READ_SIZE < end) { - Logger::error("Fixed point fraction parse will only use the first ", READ_SIZE, - " characters of ", std::string_view { str, static_cast(end - str) }); - end = str + READ_SIZE; + static constexpr FP parse_fraction(char const* str, char const* end, bool* successful) { + char const* const read_end = str + FPLUT::PRECISION; + if (read_end < end) end = read_end; + uint64_t parsed_value = StringUtils::string_to_uint64(str, end, successful, 10); + while (end++ < read_end) { + parsed_value *= 10; } - int64_t parsed_value = StringUtils::string_to_int64(str, end, successful, 10); - return parse_raw(parsed_value * 65536 / 100000); + uint64_t decimal = NumberUtils::pow(static_cast(10), FPLUT::PRECISION); + int64_t ret = 0; + for (int i = FPLUT::PRECISION - 1; i >= 0; --i) { + decimal >>= 1; + if (parsed_value > decimal) { + parsed_value -= decimal; + ret |= 1 << i; + } + } + return ret; } }; -- cgit v1.2.3-56-ga3b1