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 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)

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};
}
/**
* @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 */
Unit<Derived, T>& operator/=(T number) {
_value /= number;
@ -171,6 +219,39 @@ template<template<class> class Derived, class T> class Unit {
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 */
constexpr T operator/(Unit<Derived, T> other) const {
return _value/other._value;

Loading…
Cancel
Save