diff --git a/src/Math/CMakeLists.txt b/src/Math/CMakeLists.txt index 1b7647b1c..813349648 100644 --- a/src/Math/CMakeLists.txt +++ b/src/Math/CMakeLists.txt @@ -15,6 +15,7 @@ set(MagnumMath_HEADERS Quaternion.h RectangularMatrix.h Swizzle.h + Unit.h Vector.h Vector2.h Vector3.h diff --git a/src/Math/Math.h b/src/Math/Math.h index 6259f89c2..88557f8d1 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -41,6 +41,8 @@ template class Quaternion; template class RectangularMatrix; +template class, class> class Unit; + template class Vector; template class Vector2; template class Vector3; diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index 22b5ff493..e6bee9a10 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -16,6 +16,7 @@ corrade_add_test(MathMatrix3Test Matrix3Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathUnitTest UnitTest.cpp) corrade_add_test(MathComplexTest ComplexTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathDualTest DualTest.cpp) diff --git a/src/Math/Test/UnitTest.cpp b/src/Math/Test/UnitTest.cpp new file mode 100644 index 000000000..a0a57978b --- /dev/null +++ b/src/Math/Test/UnitTest.cpp @@ -0,0 +1,138 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +#include "Math/Unit.h" + +namespace Magnum { namespace Math { namespace Test { + +class UnitTest: public Corrade::TestSuite::Tester { + public: + explicit UnitTest(); + + void construct(); + void constructDefault(); + void constructConversion(); + void compare(); + + void negated(); + void addSubtract(); + void multiplyDivide(); +}; + +UnitTest::UnitTest() { + addTests(&UnitTest::construct, + &UnitTest::constructDefault, + &UnitTest::constructConversion, + &UnitTest::compare, + + &UnitTest::negated, + &UnitTest::addSubtract, + &UnitTest::multiplyDivide); +} + +template struct Sec_; +typedef Unit Sec; +typedef Unit Secd; + +inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, Sec value) { + return debug << float(value); +} + +void UnitTest::construct() { + constexpr Sec a(25.0f); + CORRADE_COMPARE(float(a), 25.0f); +} + +void UnitTest::constructDefault() { + constexpr Sec b; + CORRADE_COMPARE(b, Sec(0.0f)); +} + +void UnitTest::constructConversion() { + constexpr Secd a(25.0); + constexpr Sec b(a); + CORRADE_COMPARE(b, Sec(25.0f)); +} + +void UnitTest::compare() { + CORRADE_VERIFY(Sec(25.0f + MathTypeTraits::epsilon()/2) == Sec(25.0f)); + CORRADE_VERIFY(Sec(25.0f + MathTypeTraits::epsilon()*2) != Sec(25.0f)); + + constexpr bool c = Sec(3.0f) < Sec(3.0f); + constexpr bool d = Sec(3.0f) <= Sec(3.0f); + constexpr bool e = Sec(3.0f) >= Sec(3.0f); + constexpr bool f = Sec(3.0f) > Sec(3.0f); + CORRADE_VERIFY(!c); + CORRADE_VERIFY(d); + CORRADE_VERIFY(e); + CORRADE_VERIFY(!f); + + constexpr bool h = Sec(2.0f) < Sec(3.0f); + constexpr bool i = Sec(2.0f) <= Sec(3.0f); + constexpr bool j = Sec(3.0f) >= Sec(2.0f); + constexpr bool k = Sec(3.0f) > Sec(2.0f); + CORRADE_VERIFY(h); + CORRADE_VERIFY(i); + CORRADE_VERIFY(j); + CORRADE_VERIFY(k); + + constexpr bool l = Sec(3.0f) < Sec(2.0f); + constexpr bool m = Sec(3.0f) <= Sec(2.0f); + constexpr bool n = Sec(2.0f) >= Sec(3.0f); + constexpr bool o = Sec(2.0f) > Sec(3.0f); + CORRADE_VERIFY(!l); + CORRADE_VERIFY(!m); + CORRADE_VERIFY(!n); + CORRADE_VERIFY(!o); +} + +void UnitTest::negated() { + constexpr Sec a(25.0f); + constexpr Sec b(-a); + CORRADE_COMPARE(b, Sec(-25.0f)); +} + +void UnitTest::addSubtract() { + constexpr Sec a(3.0f); + constexpr Sec b(-4.0f); + constexpr Sec c(-1.0f); + + constexpr Sec d = a + b; + constexpr Sec e = c - a; + CORRADE_COMPARE(d, c); + CORRADE_COMPARE(e, b); +} + +void UnitTest::multiplyDivide() { + constexpr Sec a(3.0f); + constexpr Sec b(-4.5f); + constexpr Sec c(5.0f); + + constexpr Sec d = a*-1.5f; + constexpr Sec e = -1.5f*a; + constexpr Sec f = b/-1.5f; + CORRADE_COMPARE(d, b); + CORRADE_COMPARE(e, b); + CORRADE_COMPARE(f, a); + + constexpr float g = b/a; + CORRADE_COMPARE(g, -1.5f); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Math::Test::UnitTest) diff --git a/src/Math/Unit.h b/src/Math/Unit.h new file mode 100644 index 000000000..5d2d0ecc3 --- /dev/null +++ b/src/Math/Unit.h @@ -0,0 +1,147 @@ +#ifndef Magnum_Math_Unit_h +#define Magnum_Math_Unit_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Math::Unit + */ + +#include "Math/MathTypeTraits.h" + +namespace Magnum { namespace Math { + +/** +@brief Base class for units +@tparam T Underlying data type + +@see Deg, Rad +*/ +template class Derived, class T> class Unit { + template class, class> friend class Unit; + + public: + typedef T Type; /**< @brief Underlying data type */ + + /** @brief Default constructor */ + inline constexpr /*implicit*/ Unit(): value(T(0)) {} + + /** @brief Explicit conversion from unitless type */ + inline constexpr explicit Unit(T value): value(value) {} + + /** @brief Construct from another underlying type */ + template inline constexpr explicit Unit(Unit value): value(value.value) {} + + /** @brief Explicit conversion to underlying type */ + inline constexpr explicit operator T() const { return value; } + + /** @brief Equality comparison */ + inline constexpr bool operator==(Unit other) const { + return MathTypeTraits::equals(value, other.value); + } + + /** @brief Non-equality comparison */ + inline constexpr bool operator!=(Unit other) const { + return !operator==(other); + } + + /** @brief Less than comparison */ + inline constexpr bool operator<(Unit other) const { + return value < other.value; + } + + /** @brief Greater than comparison */ + inline constexpr bool operator>(Unit other) const { + return value > other.value; + } + + /** @brief Less than or equal comparison */ + inline constexpr bool operator<=(Unit other) const { + return !operator>(other); + } + + /** @brief Greater than or equal comparison */ + inline constexpr bool operator>=(Unit other) const { + return !operator<(other); + } + + /** @brief Negated value */ + inline constexpr Unit operator-() const { + return Unit(-value); + } + + /** @brief Add and assign value */ + inline Unit& operator+=(Unit other) { + value += other.value; + return *this; + } + + /** @brief Add value */ + inline constexpr Unit operator+(Unit other) const { + return Unit(value + other.value); + } + + /** @brief Subtract and assign value */ + inline Unit& operator-=(Unit other) { + value -= other.value; + return *this; + } + + /** @brief Subtract value */ + inline constexpr Unit operator-(Unit other) const { + return Unit(value - other.value); + } + + /** @brief Multiply with number and assign */ + inline Unit& operator*=(T number) { + value *= number; + return *this; + } + + /** @brief Multiply with number */ + inline constexpr Unit operator*(T number) const { + return Unit(value*number); + } + + /** @brief Divide with number and assign */ + inline Unit& operator/=(T number) { + value /= number; + return *this; + } + + /** @brief Divide with number */ + inline constexpr Unit operator/(T number) const { + return Unit(value/number); + } + + /** @brief Ratio of two values */ + inline constexpr T operator/(Unit other) const { + return value/other.value; + } + + private: + T value; +}; + +/** @relates Unit +@brief Multiply number with value +*/ +template class Derived, class T> inline constexpr Unit operator*(typename std::common_type::type number, const Unit& value) { + return value*number; +} + +}} + +#endif