From cac82eab9d00067d83b9eab1aa3e0667db3d7dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 10 Feb 2024 22:37:22 +0100 Subject: [PATCH] Math: implement integer and float multiply and divide for Unit. Basically what Vector has already, need this for integer representation of time, i.e. that 1.0_sec*1.25 gives back 1.25_sec, where the internal representation is a 64-bit nanosecond value. --- src/Magnum/Math/Test/UnitTest.cpp | 25 +++++++++- src/Magnum/Math/Unit.h | 81 +++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Math/Test/UnitTest.cpp b/src/Magnum/Math/Test/UnitTest.cpp index cc37f36c3..2dbace246 100644 --- a/src/Magnum/Math/Test/UnitTest.cpp +++ b/src/Magnum/Math/Test/UnitTest.cpp @@ -47,6 +47,7 @@ struct UnitTest: TestSuite::Tester { void promotedNegated(); void addSubtract(); void multiplyDivide(); + void multiplyDivideIntegral(); }; UnitTest::UnitTest() { @@ -61,7 +62,8 @@ UnitTest::UnitTest() { &UnitTest::promotedNegated, &UnitTest::addSubtract, - &UnitTest::multiplyDivide}); + &UnitTest::multiplyDivide, + &UnitTest::multiplyDivideIntegral}); } /* What's a typedef and not a using differs from the typedefs in root Magnum @@ -74,6 +76,9 @@ using Magnum::Constants; inline Debug& operator<<(Debug& debug, Sec value) { return debug << Float(value); } +inline Debug& operator<<(Debug& debug, Seci value) { + return debug << Int(value); +} void UnitTest::construct() { Sec a{25.0f}; @@ -274,6 +279,24 @@ void UnitTest::multiplyDivide() { CORRADE_COMPARE(cf, -1.5f); } +void UnitTest::multiplyDivideIntegral() { + CORRADE_COMPARE(Seci{100}*1.25f, Seci{125}); + CORRADE_COMPARE(Seci{100}/0.8f, Seci{125}); + + Seci a{100}; + Seci b{125}; + a *= 1.25f; + b /= 1.25f; + CORRADE_COMPARE(a, Seci{125}); + CORRADE_COMPARE(b, Seci{100}); + + constexpr Seci ca{100}; + constexpr Seci cb = ca*1.25f; + constexpr Seci cc = ca/0.8f; + CORRADE_COMPARE(cb, Seci{125}); + CORRADE_COMPARE(cc, Seci{125}); +} + }}}} CORRADE_TEST_MAIN(Magnum::Math::Test::UnitTest) diff --git a/src/Magnum/Math/Unit.h b/src/Magnum/Math/Unit.h index 5923d8f08..34cb498a9 100644 --- a/src/Magnum/Math/Unit.h +++ b/src/Magnum/Math/Unit.h @@ -160,6 +160,54 @@ template class Derived, class T> class Unit { return Unit{value._value*number}; } + /** + * @brief Multiply an integral value with a floating-point number and assign + * @m_since_latest + * + * Similar to @ref operator*=(T), except that the multiplication is + * done in floating-point. + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + template Unit& + #else + template typename std::enable_if::value && std::is_floating_point::value, Unit&>::type + #endif + operator*=(FloatingPoint number) { + _value = T(_value*number); + return *this; + } + + /** + * @brief Multiply an integral value with a floating-point number + * @m_since_latest + * + * Similar to @ref operator*(T) const, except that the multiplication + * is done in floating-point. + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + template constexpr Unit + #else + template constexpr typename std::enable_if::value && std::is_floating_point::value, Unit>::type + #endif + operator*(FloatingPoint number) const { + return Unit{T(_value*number)}; + } + + /** + * @brief Multiply a floating-point number with an integral value + * @m_since_latest + * + * Same as @ref operator*(FloatingPoint) const. + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + template friend constexpr Unit + #else + template friend constexpr typename std::enable_if::value && std::is_floating_point::value, Unit>::type + #endif + operator*(FloatingPoint number, const Unit& value) { + return Unit{T(value._value*number)}; + } + /** @brief Divide with a number and assign */ Unit& operator/=(T number) { _value /= number; @@ -171,6 +219,39 @@ template class Derived, class T> class Unit { return Unit(_value/number); } + /** + * @brief Divide an integral value with a floating-point number and assign + * @m_since_latest + * + * Similar to @ref operator/=(T), except that the division is done in + * floating-point. + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + template Unit& + #else + template typename std::enable_if::value && std::is_floating_point::value, Unit&>::type + #endif + operator/=(FloatingPoint number) { + _value = T(_value/number); + return *this; + } + + /** + * @brief Divide an integral value with a floating-point number + * @m_since_latest + * + * Similar to @ref operator/(T) const, except that the division is done + * in floating-point. + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + template constexpr Unit + #else + template constexpr typename std::enable_if::value && std::is_floating_point::value, Unit>::type + #endif + operator/(FloatingPoint number) const { + return Unit{T(_value/number)}; + } + /** @brief Ratio of two values */ constexpr T operator/(Unit other) const { return _value/other._value;