Browse Source

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.
pull/638/head
Vladimír Vondruš 2 years ago
parent
commit
cac82eab9d
  1. 25
      src/Magnum/Math/Test/UnitTest.cpp
  2. 81
      src/Magnum/Math/Unit.h

25
src/Magnum/Math/Test/UnitTest.cpp

@ -47,6 +47,7 @@ struct UnitTest: TestSuite::Tester {
void promotedNegated(); void promotedNegated();
void addSubtract(); void addSubtract();
void multiplyDivide(); void multiplyDivide();
void multiplyDivideIntegral();
}; };
UnitTest::UnitTest() { UnitTest::UnitTest() {
@ -61,7 +62,8 @@ UnitTest::UnitTest() {
&UnitTest::promotedNegated, &UnitTest::promotedNegated,
&UnitTest::addSubtract, &UnitTest::addSubtract,
&UnitTest::multiplyDivide}); &UnitTest::multiplyDivide,
&UnitTest::multiplyDivideIntegral});
} }
/* What's a typedef and not a using differs from the typedefs in root Magnum /* 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) { inline Debug& operator<<(Debug& debug, Sec value) {
return debug << Float(value); return debug << Float(value);
} }
inline Debug& operator<<(Debug& debug, Seci value) {
return debug << Int(value);
}
void UnitTest::construct() { void UnitTest::construct() {
Sec a{25.0f}; Sec a{25.0f};
@ -274,6 +279,24 @@ void UnitTest::multiplyDivide() {
CORRADE_COMPARE(cf, -1.5f); 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) CORRADE_TEST_MAIN(Magnum::Math::Test::UnitTest)

81
src/Magnum/Math/Unit.h

@ -160,6 +160,54 @@ template<template<class> class Derived, class T> class Unit {
return Unit<Derived, T>{value._value*number}; return Unit<Derived, T>{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<class FloatingPoint> Unit<Derived, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>&>::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<class FloatingPoint> constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator*(FloatingPoint number) const {
return Unit<Derived, T>{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<class FloatingPoint> friend constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> friend constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator*(FloatingPoint number, const Unit<Derived, T>& value) {
return Unit<Derived, T>{T(value._value*number)};
}
/** @brief Divide with a number and assign */ /** @brief Divide with a number and assign */
Unit<Derived, T>& operator/=(T number) { Unit<Derived, T>& operator/=(T number) {
_value /= number; _value /= number;
@ -171,6 +219,39 @@ template<template<class> class Derived, class T> class Unit {
return Unit<Derived, T>(_value/number); return Unit<Derived, T>(_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<class FloatingPoint> Unit<Derived, T>&
#else
template<class FloatingPoint, class Integral = T> typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>&>::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<class FloatingPoint> constexpr Unit<Derived, T>
#else
template<class FloatingPoint, class Integral = T> constexpr typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Unit<Derived, T>>::type
#endif
operator/(FloatingPoint number) const {
return Unit<Derived, T>{T(_value/number)};
}
/** @brief Ratio of two values */ /** @brief Ratio of two values */
constexpr T operator/(Unit<Derived, T> other) const { constexpr T operator/(Unit<Derived, T> other) const {
return _value/other._value; return _value/other._value;

Loading…
Cancel
Save