From 1308cb4e2db1eb117b53372bc4fe964cf2d96813 Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 1 Dec 2021 13:52:38 +0800 Subject: =?UTF-8?q?*fpm=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9Bfloat=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Client/Source/Phy2DLite/Settings.h | 56 ++++- Client/Source/Phy2DLite/Tests/test_p2d.cpp | 4 +- Client/ThirdParty/fpm/include/fpm/fixed.hpp | 311 ++++++++++++++++------------ Client/ThirdParty/fpm/include/fpm/math.hpp | 2 +- 4 files changed, 234 insertions(+), 139 deletions(-) (limited to 'Client') diff --git a/Client/Source/Phy2DLite/Settings.h b/Client/Source/Phy2DLite/Settings.h index e976e26..e50646c 100644 --- a/Client/Source/Phy2DLite/Settings.h +++ b/Client/Source/Phy2DLite/Settings.h @@ -4,13 +4,59 @@ #define NUMBER_LIBFIX 2 #define NUMBER_FPM 3 -#define NUMBER_ALIAS NUMBER_LIBFIX +#define NUMBER_ALIAS NUMBER_FPM #if NUMBER_ALIAS == NUMBER_LIBFIX #include "libfixmath/libfixmath/fixmath.h" #elif NUMBER_ALIAS == NUMBER_FPM #include "fpm/include/fpm/fixed.hpp" #include "fpm/include/fpm/math.hpp" + +template +struct Limits {}; + +template <> +struct Limits +{ + static constexpr bool is_signed() noexcept { return true; } + static constexpr int digits() noexcept { return 31; } + static constexpr int max_digits10() noexcept { return 5 + 5; } + static constexpr int min_exponent() noexcept { return -15; } + static constexpr int max_exponent() noexcept { return 15; } + static constexpr int min_exponent10() noexcept { return -4; } + static constexpr int max_exponent10() noexcept { return 4; } + static constexpr fpm::fixed_16_16 min() noexcept { return fpm::fixed_16_16::from_raw_value(-2147483647 - 1); } + static constexpr fpm::fixed_16_16 max() noexcept { return fpm::fixed_16_16::from_raw_value(2147483647); } +}; + +template <> +struct Limits +{ + static constexpr bool is_signed() noexcept { return true; } + static constexpr int digits() noexcept { return 31; } + static constexpr int max_digits10() noexcept { return 7 + 3; } + static constexpr int min_exponent() noexcept { return -7; } + static constexpr int max_exponent() noexcept { return 23; } + static constexpr int min_exponent10() noexcept { return -2; } + static constexpr int max_exponent10() noexcept { return 6; } + static constexpr fpm::fixed_24_8 min() noexcept { return fpm::fixed_24_8::from_raw_value(-2147483647 - 1); } + static constexpr fpm::fixed_24_8 max() noexcept { return fpm::fixed_24_8::from_raw_value(2147483647); } +}; + +template <> +struct Limits +{ + static constexpr bool is_signed() noexcept { return true; } + static constexpr int digits() noexcept { return 31; } + static constexpr int max_digits10() noexcept { return 3 + 8; } + static constexpr int min_exponent() noexcept { return -23; } + static constexpr int max_exponent() noexcept { return 7; } + static constexpr int min_exponent10() noexcept { return -7; } + static constexpr int max_exponent10() noexcept { return 2; } + static constexpr fpm::fixed_8_24 min() noexcept { return fpm::fixed_8_24::from_raw_value(-2147483647 - 1); } + static constexpr fpm::fixed_8_24 max() noexcept { return fpm::fixed_8_24::from_raw_value(2147483647); } +}; + #endif namespace Phy2D @@ -38,13 +84,13 @@ typedef Fix16 number; #elif NUMBER_ALIAS == NUMBER_FPM typedef fpm::fixed_16_16 number; -#define NUMBER_MAX (number::max()) -#define NUMBER_MIN (number::min()) +#define NUMBER_MAX (Limits::max()) +#define NUMBER_MIN (Limits::min()) #define SQRT(a) (fpm::sqrt((a))) #define SIN(a) (fpm::sin((a))) #define COS(a) (fpm::cos((a))) +#define PI (number::pi()) #endif -} - +} \ No newline at end of file diff --git a/Client/Source/Phy2DLite/Tests/test_p2d.cpp b/Client/Source/Phy2DLite/Tests/test_p2d.cpp index a668301..69737f6 100644 --- a/Client/Source/Phy2DLite/Tests/test_p2d.cpp +++ b/Client/Source/Phy2DLite/Tests/test_p2d.cpp @@ -292,7 +292,7 @@ static void Demo7(Body* b, Joint* j) float dampingRatio = 0.7f; // frequency in radians - float omega = (number)2.0f * fix16_pi * frequencyHz; + float omega = (number)2.0f * PI * frequencyHz; // damping coefficient float d = 2.0f * mass * dampingRatio * omega; @@ -418,7 +418,7 @@ static void Demo9(Body* b, Joint* j) float dampingRatio = 0.7f; // frequency in radians - float omega = (number) 2.0f * fix16_pi * frequencyHz; + float omega = (number) 2.0f * PI * frequencyHz; // damping coefficient float d = 2.0f * mass * dampingRatio * omega; diff --git a/Client/ThirdParty/fpm/include/fpm/fixed.hpp b/Client/ThirdParty/fpm/include/fpm/fixed.hpp index 9feff29..b900dd0 100644 --- a/Client/ThirdParty/fpm/include/fpm/fixed.hpp +++ b/Client/ThirdParty/fpm/include/fpm/fixed.hpp @@ -36,34 +36,34 @@ namespace fpm // Converts an integral number to the fixed-point type. // Like static_cast, this truncates bits that don't fit. template ::value>::type* = nullptr> - constexpr inline explicit fixed(T val) noexcept + constexpr inline /*explicit*/ fixed(T val) noexcept : m_value(static_cast(val * FRACTION_MULT)) {} // Converts an floating-point number to the fixed-point type. // Like static_cast, this truncates bits that don't fit. template ::value>::type* = nullptr> - constexpr inline explicit fixed(T val) noexcept + constexpr inline /*explicit*/ fixed(T val) noexcept : m_value(static_cast((val >= 0.0) ? (val * FRACTION_MULT + T{0.5}) : (val * FRACTION_MULT - T{0.5}))) {} // Constructs from another fixed-point type with possibly different underlying representation. // Like static_cast, this truncates bits that don't fit. template - constexpr inline explicit fixed(fixed val) noexcept + constexpr inline /*explicit*/ fixed(fixed val) noexcept : m_value(from_fixed_point(val.raw_value()).raw_value()) {} // Explicit conversion to a floating-point type template ::value>::type* = nullptr> - constexpr inline explicit operator T() const noexcept + constexpr inline /*explicit*/ operator T() const noexcept { return static_cast(m_value) / FRACTION_MULT; } // Explicit conversion to an integral type template ::value>::type* = nullptr> - constexpr inline explicit operator T() const noexcept + constexpr inline /*explicit*/ operator T() const noexcept { return static_cast(m_value / FRACTION_MULT); } @@ -248,6 +248,13 @@ namespace fpm return fixed(x) *= y; } + template + constexpr inline fixed operator*(const fixed& x, T y) noexcept + { + fixed r = y; + return fixed(x) *= r; + } + template ::value>::type* = nullptr> constexpr inline fixed operator*(const fixed& x, T y) noexcept { @@ -270,6 +277,13 @@ namespace fpm return fixed(x) /= y; } + template + constexpr inline fixed operator/(const fixed& x, T y) noexcept + { + fixed r = y; + return fixed(x) /= r; + } + template ::value>::type* = nullptr> constexpr inline fixed operator/(const fixed& x, T y) noexcept { @@ -292,30 +306,65 @@ namespace fpm return x.raw_value() == y.raw_value(); } + template + constexpr inline bool operator==(const fixed& x, T y) noexcept + { + fixed r = y; + return x.raw_value() == r.raw_value(); + } + template constexpr inline bool operator!=(const fixed& x, const fixed& y) noexcept { return x.raw_value() != y.raw_value(); } + template + constexpr inline bool operator!=(const fixed& x, T y) noexcept + { + fixed r = y; + return x.raw_value() != r.raw_value(); + } + template constexpr inline bool operator<(const fixed& x, const fixed& y) noexcept { return x.raw_value() < y.raw_value(); } + template + constexpr inline bool operator<(const fixed& x, T y) noexcept + { + fixed r = y; + return x.raw_value() < r.raw_value(); + } + template constexpr inline bool operator>(const fixed& x, const fixed& y) noexcept { return x.raw_value() > y.raw_value(); } + template + constexpr inline bool operator>(const fixed& x, T y) noexcept + { + fixed r = y; + return x.raw_value() > r.raw_value(); + } + template constexpr inline bool operator<=(const fixed& x, const fixed& y) noexcept { return x.raw_value() <= y.raw_value(); } + template + constexpr inline bool operator<=(const fixed& x, T y) noexcept + { + fixed r = y; + return x.raw_value() <= r.raw_value(); + } + template constexpr inline bool operator>=(const fixed& x, const fixed& y) noexcept { @@ -324,21 +373,21 @@ namespace fpm namespace detail { - // Number of base-10 digits required to fully represent a number of bits - static constexpr int max_digits10(int bits) - { - // 8.24 fixed-point equivalent of (int)ceil(bits * std::log10(2)); - using T = long long; - return static_cast((T{bits} * 5050445 + (T{1} << 24) - 1) >> 24); - } + // Number of base-10 digits required to fully represent a number of bits + static constexpr int max_digits10(int bits) + { + // 8.24 fixed-point equivalent of (int)ceil(bits * std::log10(2)); + using T = long long; + return static_cast((T{bits} * 5050445 + (T{1} << 24) - 1) >> 24); + } - // Number of base-10 digits that can be fully represented by a number of bits - static constexpr int digits10(int bits) - { - // 8.24 fixed-point equivalent of (int)(bits * std::log10(2)); - using T = long long; - return static_cast((T{bits} * 5050445) >> 24); - } + // Number of base-10 digits that can be fully represented by a number of bits + static constexpr int digits10(int bits) + { + // 8.24 fixed-point equivalent of (int)(bits * std::log10(2)); + using T = long long; + return static_cast((T{bits} * 5050445) >> 24); + } } // namespace detail @@ -348,127 +397,127 @@ namespace fpm namespace std { -template -struct hash> -{ - using argument_type = fpm::fixed; - using result_type = std::size_t; - - result_type operator()(argument_type arg) const noexcept(noexcept(std::declval>()(arg.raw_value()))) { - return m_hash(arg.raw_value()); - } + template + struct hash> + { + using argument_type = fpm::fixed; + using result_type = std::size_t; -private: - std::hash m_hash; -}; + result_type operator()(argument_type arg) const noexcept(noexcept(std::declval>()(arg.raw_value()))) { + return m_hash(arg.raw_value()); + } -template -struct numeric_limits> -{ - static constexpr bool is_specialized = true; - static constexpr bool is_signed = std::numeric_limits::is_signed; - static constexpr bool is_integer = false; - static constexpr bool is_exact = true; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr bool has_denorm = std::denorm_absent; - static constexpr bool has_denorm_loss = false; - static constexpr std::float_round_style round_style = std::round_to_nearest; - static constexpr bool is_iec_559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = std::numeric_limits::is_modulo; - static constexpr int digits = std::numeric_limits::digits; - - // Any number with `digits10` significant base-10 digits (that fits in - // the range of the type) is guaranteed to be convertible from text and - // back without change. Worst case, this is 0.000...001, so we can only - // guarantee this case. Nothing more. - static constexpr int digits10 = 1; - - // This is equal to max_digits10 for the integer and fractional part together. - static constexpr int max_digits10 = - fpm::detail::max_digits10(std::numeric_limits::digits - F) + fpm::detail::max_digits10(F); - - static constexpr int radix = 2; - static constexpr int min_exponent = 1 - F; - static constexpr int min_exponent10 = -fpm::detail::digits10(F); - static constexpr int max_exponent = std::numeric_limits::digits - F; - static constexpr int max_exponent10 = fpm::detail::digits10(std::numeric_limits::digits - F); - static constexpr bool traps = true; - static constexpr bool tinyness_before = false; - - static constexpr fpm::fixed lowest() noexcept { - return fpm::fixed::from_raw_value(std::numeric_limits::lowest()); + private: + std::hash m_hash; }; - static constexpr fpm::fixed min() noexcept { - return lowest(); - } + template + struct numeric_limits> + { + static constexpr bool is_specialized = true; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = false; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm = std::denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr std::float_round_style round_style = std::round_to_nearest; + static constexpr bool is_iec_559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = std::numeric_limits::is_modulo; + static constexpr int digits = std::numeric_limits::digits; + + // Any number with `digits10` significant base-10 digits (that fits in + // the range of the type) is guaranteed to be convertible from text and + // back without change. Worst case, this is 0.000...001, so we can only + // guarantee this case. Nothing more. + static constexpr int digits10 = 1; + + // This is equal to max_digits10 for the integer and fractional part together. + static constexpr int max_digits10 = + fpm::detail::max_digits10(std::numeric_limits::digits - F) + fpm::detail::max_digits10(F); + + static constexpr int radix = 2; + static constexpr int min_exponent = 1 - F; + static constexpr int min_exponent10 = -fpm::detail::digits10(F); + static constexpr int max_exponent = std::numeric_limits::digits - F; + static constexpr int max_exponent10 = fpm::detail::digits10(std::numeric_limits::digits - F); + static constexpr bool traps = true; + static constexpr bool tinyness_before = false; + + static constexpr fpm::fixed lowest() noexcept { + return fpm::fixed::from_raw_value(std::numeric_limits::lowest()); + }; + + static constexpr fpm::fixed min() noexcept { + return lowest(); + } - static constexpr fpm::fixed max() noexcept { - return fpm::fixed::from_raw_value(std::numeric_limits::max()); - }; + static constexpr fpm::fixed max() noexcept { + return fpm::fixed::from_raw_value(std::numeric_limits::max()); + }; - static constexpr fpm::fixed epsilon() noexcept { - return fpm::fixed::from_raw_value(1); - }; + static constexpr fpm::fixed epsilon() noexcept { + return fpm::fixed::from_raw_value(1); + }; - static constexpr fpm::fixed round_error() noexcept { - return fpm::fixed(1) / 2; + static constexpr fpm::fixed round_error() noexcept { + return fpm::fixed(1) / 2; + }; + + static constexpr fpm::fixed denorm_min() noexcept { + return min(); + } }; - static constexpr fpm::fixed denorm_min() noexcept { - return min(); - } -}; - -template -constexpr bool numeric_limits>::is_specialized; -template -constexpr bool numeric_limits>::is_signed; -template -constexpr bool numeric_limits>::is_integer; -template -constexpr bool numeric_limits>::is_exact; -template -constexpr bool numeric_limits>::has_infinity; -template -constexpr bool numeric_limits>::has_quiet_NaN; -template -constexpr bool numeric_limits>::has_signaling_NaN; -template -constexpr bool numeric_limits>::has_denorm; -template -constexpr bool numeric_limits>::has_denorm_loss; -template -constexpr std::float_round_style numeric_limits>::round_style; -template -constexpr bool numeric_limits>::is_iec_559; -template -constexpr bool numeric_limits>::is_bounded; -template -constexpr bool numeric_limits>::is_modulo; -template -constexpr int numeric_limits>::digits; -template -constexpr int numeric_limits>::digits10; -template -constexpr int numeric_limits>::max_digits10; -template -constexpr int numeric_limits>::radix; -template -constexpr int numeric_limits>::min_exponent; -template -constexpr int numeric_limits>::min_exponent10; -template -constexpr int numeric_limits>::max_exponent; -template -constexpr int numeric_limits>::max_exponent10; -template -constexpr bool numeric_limits>::traps; -template -constexpr bool numeric_limits>::tinyness_before; + template + constexpr bool numeric_limits>::is_specialized; + template + constexpr bool numeric_limits>::is_signed; + template + constexpr bool numeric_limits>::is_integer; + template + constexpr bool numeric_limits>::is_exact; + template + constexpr bool numeric_limits>::has_infinity; + template + constexpr bool numeric_limits>::has_quiet_NaN; + template + constexpr bool numeric_limits>::has_signaling_NaN; + template + constexpr bool numeric_limits>::has_denorm; + template + constexpr bool numeric_limits>::has_denorm_loss; + template + constexpr std::float_round_style numeric_limits>::round_style; + template + constexpr bool numeric_limits>::is_iec_559; + template + constexpr bool numeric_limits>::is_bounded; + template + constexpr bool numeric_limits>::is_modulo; + template + constexpr int numeric_limits>::digits; + template + constexpr int numeric_limits>::digits10; + template + constexpr int numeric_limits>::max_digits10; + template + constexpr int numeric_limits>::radix; + template + constexpr int numeric_limits>::min_exponent; + template + constexpr int numeric_limits>::min_exponent10; + template + constexpr int numeric_limits>::max_exponent; + template + constexpr int numeric_limits>::max_exponent10; + template + constexpr bool numeric_limits>::traps; + template + constexpr bool numeric_limits>::tinyness_before; } diff --git a/Client/ThirdParty/fpm/include/fpm/math.hpp b/Client/ThirdParty/fpm/include/fpm/math.hpp index cf45297..3943940 100644 --- a/Client/ThirdParty/fpm/include/fpm/math.hpp +++ b/Client/ThirdParty/fpm/include/fpm/math.hpp @@ -538,7 +538,7 @@ fixed sin(fixed x) noexcept } const Fixed x2 = x*x; - return sign * x * (Fixed::pi() - x2*(Fixed::two_pi() - 5 - x2*(Fixed::pi() - 3)))/2; + return sign * x * (Fixed::pi() - x2*(Fixed::two_pi() - 5 - x2*(Fixed::pi() - 3)))/2.f; } template -- cgit v1.1-26-g67d0