From f7f2ab8cb5b5590c455aafbb53a4458d1d76aeb6 Mon Sep 17 00:00:00 2001 From: Borislav Stanimirov Date: Sat, 8 Dec 2018 18:06:33 +0200 Subject: [PATCH] Math: added StrictWeakOrdering for math types --- doc/snippets/MagnumMath.cpp | 13 ++ src/Magnum/Math/Bezier.h | 16 ++ src/Magnum/Math/BoolVector.h | 22 +++ src/Magnum/Math/CMakeLists.txt | 1 + src/Magnum/Math/Color.h | 4 + src/Magnum/Math/Complex.h | 14 ++ src/Magnum/Math/CubicHermite.h | 17 ++ src/Magnum/Math/Dual.h | 15 ++ src/Magnum/Math/DualComplex.h | 5 + src/Magnum/Math/DualQuaternion.h | 5 + src/Magnum/Math/Half.h | 8 + src/Magnum/Math/Math.h | 4 + src/Magnum/Math/Matrix.h | 2 + src/Magnum/Math/Matrix3.h | 5 + src/Magnum/Math/Matrix4.h | 5 + src/Magnum/Math/Quaternion.h | 15 ++ src/Magnum/Math/Range.h | 13 ++ src/Magnum/Math/RectangularMatrix.h | 17 ++ src/Magnum/Math/StrictWeakOrdering.h | 78 ++++++++ src/Magnum/Math/Test/BezierTest.cpp | 20 ++ src/Magnum/Math/Test/BoolVectorTest.cpp | 37 ++++ src/Magnum/Math/Test/CMakeLists.txt | 5 + src/Magnum/Math/Test/ColorTest.cpp | 31 +++ src/Magnum/Math/Test/ComplexTest.cpp | 20 ++ src/Magnum/Math/Test/CubicHermiteTest.cpp | 25 +++ src/Magnum/Math/Test/DualComplexTest.cpp | 20 ++ src/Magnum/Math/Test/DualQuaternionTest.cpp | 20 ++ src/Magnum/Math/Test/DualTest.cpp | 20 ++ src/Magnum/Math/Test/HalfTest.cpp | 15 ++ src/Magnum/Math/Test/Matrix3Test.cpp | 21 +++ src/Magnum/Math/Test/Matrix4Test.cpp | 21 +++ src/Magnum/Math/Test/MatrixTest.cpp | 21 +++ src/Magnum/Math/Test/QuaternionTest.cpp | 21 +++ src/Magnum/Math/Test/RangeTest.cpp | 21 +++ .../Math/Test/RectangularMatrixTest.cpp | 21 +++ .../Math/Test/StrictWeakOrderingTest.cpp | 178 ++++++++++++++++++ src/Magnum/Math/Test/Vector2Test.cpp | 21 +++ src/Magnum/Math/Test/Vector3Test.cpp | 21 +++ src/Magnum/Math/Test/Vector4Test.cpp | 21 +++ src/Magnum/Math/Test/VectorTest.cpp | 49 +++++ src/Magnum/Math/Vector.h | 16 ++ src/Magnum/Math/Vector2.h | 2 + src/Magnum/Math/Vector3.h | 2 + src/Magnum/Math/Vector4.h | 2 + 44 files changed, 910 insertions(+) create mode 100644 src/Magnum/Math/StrictWeakOrdering.h create mode 100644 src/Magnum/Math/Test/StrictWeakOrderingTest.cpp diff --git a/doc/snippets/MagnumMath.cpp b/doc/snippets/MagnumMath.cpp index c91bd31d8..faf3e2eca 100644 --- a/doc/snippets/MagnumMath.cpp +++ b/doc/snippets/MagnumMath.cpp @@ -32,6 +32,10 @@ #include "Magnum/Math/Half.h" #include "Magnum/Math/Range.h" #include "Magnum/Math/Algorithms/GramSchmidt.h" +#include "Magnum/Math/StrictWeakOrdering.h" + +#include +#include using namespace Magnum; using namespace Magnum::Math::Literals; @@ -902,4 +906,13 @@ auto filterArea = Range2Di::fromSize(center, Vector2i{1}).padded(filterRadius); static_cast(filterArea); } +{ +/* [StrictWeakOrdering] */ +std::set mySet; +std::map myMap; +/* [StrictWeakOrdering] */ +static_cast(myMap); +static_cast(mySet); +} + } diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h index 1eee72bca..a46f0caa3 100644 --- a/src/Magnum/Math/Bezier.h +++ b/src/Magnum/Math/Bezier.h @@ -317,6 +317,22 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Bezier<3, 3, Double>&); #endif +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Bezier& a, const Bezier& b) const { + StrictWeakOrdering> o; + for(std::size_t i = 0; i < order + 1; ++i) { + if(o(a[i], b[i])) + return true; + if(o(b[i], a[i])) + return false; + } + + return false; // a and b are equivalent + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/BoolVector.h b/src/Magnum/Math/BoolVector.h index ad133882a..9364d0c7b 100644 --- a/src/Magnum/Math/BoolVector.h +++ b/src/Magnum/Math/BoolVector.h @@ -33,6 +33,7 @@ #include #include "Magnum/Types.h" +#include "Magnum/Math/Math.h" #include "Magnum/Math/Tags.h" namespace Magnum { namespace Math { @@ -303,6 +304,27 @@ template inline BoolVector BoolVector::operator~() return out; } +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const BoolVector& a, const BoolVector& b) const { + auto ad = a.data(); + auto bd = b.data(); + for(std::size_t i = 0; i < BoolVector::DataSize - 1; ++i) { + if(ad[i] < bd[i]) + return true; + if(ad[i] > bd[i]) + return false; + } + + // mask last element with to hide unused bits + constexpr UnsignedByte mask = UnsignedByte(0xFF) >> (BoolVector::DataSize * 8 - size); + constexpr std::size_t i = BoolVector::DataSize - 1; + return (ad[i] & mask) < (bd[i] & mask); + } +}; +} + }} #endif diff --git a/src/Magnum/Math/CMakeLists.txt b/src/Magnum/Math/CMakeLists.txt index b5510e744..670cc496e 100644 --- a/src/Magnum/Math/CMakeLists.txt +++ b/src/Magnum/Math/CMakeLists.txt @@ -48,6 +48,7 @@ set(MagnumMath_HEADERS Packing.h Range.h RectangularMatrix.h + StrictWeakOrdering.h Swizzle.h Tags.h Unit.h diff --git a/src/Magnum/Math/Color.h b/src/Magnum/Math/Color.h index 36a0aebbf..6dd059f78 100644 --- a/src/Magnum/Math/Color.h +++ b/src/Magnum/Math/Color.h @@ -1272,6 +1272,10 @@ namespace Implementation { template struct TypeForSize<3, Color4> { typedef Color3 Type; }; template struct TypeForSize<4, Color3> { typedef Color4 Type; }; template struct TypeForSize<4, Color4> { typedef Color4 Type; }; + + template struct StrictWeakOrdering> : public StrictWeakOrdering> {}; + template struct StrictWeakOrdering> : public StrictWeakOrdering> {}; + } }} diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index ab90c3235..4f5c4f885 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -620,6 +620,20 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Complex&); #endif +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Complex& a, const Complex& b) const { + if(a.real() < b.real()) + return true; + if(a.real() > b.real()) + return false; + + return a.imaginary() < b.imaginary(); + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/CubicHermite.h b/src/Magnum/Math/CubicHermite.h index 4c7dc1942..480261d4c 100644 --- a/src/Magnum/Math/CubicHermite.h +++ b/src/Magnum/Math/CubicHermite.h @@ -538,6 +538,23 @@ template inline bool CubicHermite::operator==(const CubicHermite& TypeTraits::equals(_outTangent, other._outTangent); } +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const CubicHermite& a, const CubicHermite& b) const { + StrictWeakOrdering o; + if(o(a.inTangent(), b.inTangent())) + return true; + if(o(b.inTangent(), a.inTangent())) + return false; + if(o(a.point(), b.point())) + return true; + if(o(b.point(), a.point())) + return false; + return o(a.outTangent(), b.outTangent()); + } +}; +} + }} #endif diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index fd4a3a9dd..8f8ef1319 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -395,6 +395,21 @@ template std::pair, Dual> sincos(const Dual>& a template std::pair, Dual> sincos(const Dual>& angle) { return sincos(Dual>(angle)); } #endif +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Dual& a, const Dual& b) const { + StrictWeakOrdering o; + if(o(a.real(), b.real())) + return true; + if(o(b.real(), a.real())) + return false; + + return o(a.dual(), b.dual()); + } +}; +} + }} #endif diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index 4e9e6ca34..7f86fc1b5 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -385,6 +385,11 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualComplex&); #endif +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering>: public StrictWeakOrdering>> {}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 42114404c..ab1716084 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -545,6 +545,11 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const DualQuaternion&); #endif +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering>: public StrictWeakOrdering>> {}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/Half.h b/src/Magnum/Math/Half.h index f957fd09c..077e9c043 100644 --- a/src/Magnum/Math/Half.h +++ b/src/Magnum/Math/Half.h @@ -161,6 +161,14 @@ Prints the value with 4 significant digits. */ MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& debug, Half value); +namespace Implementation { +template <> struct StrictWeakOrdering { + bool operator()(Half a, Half b) const { + return a.data() < b.data(); // Not mathematically equivalent to <, but does order + } +}; +} + }} #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) diff --git a/src/Magnum/Math/Math.h b/src/Magnum/Math/Math.h index e721e2c95..307e41d63 100644 --- a/src/Magnum/Math/Math.h +++ b/src/Magnum/Math/Math.h @@ -101,6 +101,10 @@ template class Range; template using Range1D = Range<1, T>; template class Range2D; template class Range3D; + +namespace Implementation { +template struct StrictWeakOrdering; +} #endif }} diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 56773bc3f..df9d478a5 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -321,6 +321,8 @@ template struct MatrixDeterminant<1, T> { } }; +template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; + } #endif diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index 8c1e12a93..9fae67e71 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -692,6 +692,11 @@ template inline Matrix3 Matrix3::invertedRigid() const { return from(inverseRotation, inverseRotation*-translation()); } +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index e4abe28ea..4b0bc90ba 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -1024,6 +1024,11 @@ template Matrix4 Matrix4::invertedRigid() const { return from(inverseRotation, inverseRotation*-translation()); } +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 91e27b569..be8e4e051 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -739,6 +739,21 @@ template inline Vector3 Quaternion::transformVectorNormalized(con return vector + _scalar*t + Math::cross(_vector, t); } +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Quaternion& a, const Quaternion& b) const { + StrictWeakOrdering> o; + if(o(a.vector(), b.vector())) + return true; + if(o(b.vector(), a.vector())) + return false; + + return a.scalar() < b.scalar(); + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index 4be27c574..12e61c699 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -759,6 +759,19 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug&, const Range<3, Double>&); #endif +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Range& a, const Range& b) const { + StrictWeakOrdering::VectorType> o; + if(o(a.min(), b.min())) + return true; + if(o(b.min(), a.min())) + return false; + return o(a.max(), b.max()); + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 2738dff3c..b99129374 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -760,6 +760,23 @@ template template struct StrictWeakOrdering> { + bool operator()(const RectangularMatrix& a, const RectangularMatrix& b) const { + StrictWeakOrdering> o; + for(std::size_t i = 0; i < cols; ++i) { + if(o(a[i], b[i])) + return true; + if(o(b[i], a[i])) + return false; + } + + return false; // a and b are equivalent + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/StrictWeakOrdering.h b/src/Magnum/Math/StrictWeakOrdering.h new file mode 100644 index 000000000..6cbe661bc --- /dev/null +++ b/src/Magnum/Math/StrictWeakOrdering.h @@ -0,0 +1,78 @@ +#ifndef Magnum_Math_StrictWeakOrdering_h +#define Magnum_Math_StrictWeakOrdering_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Math::StrictWeakOrdering + */ + +namespace Magnum { namespace Math { + +namespace Implementation { +template struct StrictWeakOrdering { // Specialized for supported types + bool operator()(const T& a, const T& b) const { + return a < b; + } +}; +} + +/** +@brief A functor which implements strict weak ordering for all types in the Math library. + +A strict weak ordering enables a comparison operator between to elements of a +set. With it an ordering can be achieved between the elements. + +This is useful mainly for interoperability with ordering containers from the +C++ standard library, like @ref std::map and @ref std::set. + +@snippet MagnumMath.cpp StrictWeakOrdering + +Check the source for defails if you want to create an implementation for your +own types. + */ +struct StrictWeakOrdering { + /** + * @brief Compares two items. + * + * Returns true if a is less than b. + * + * Returns false if a is equivalent to b or greater. + * + * For scalar types this is equivalent to operator < + */ + template bool operator()(const T& a, const T& b) const { + // Instantiate a specialization of Implementation::StrictWeakOrdering + // If users want to enable this for their own types, they must create + // a specialization of Magnum::Math::Implementation::StrictWeakOrdering + // for them. + Implementation::StrictWeakOrdering o; + return o(a, b); + } +}; + +}} + +#endif diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index f5f25ba08..65a28ef20 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -32,6 +32,7 @@ #include "Magnum/Math/CubicHermite.h" #include "Magnum/Math/Vector2.h" #include "Magnum/Math/Functions.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct QBezier2D { float x0, x1, x2, y0, y1, y2; @@ -85,6 +86,8 @@ struct BezierTest: Corrade::TestSuite::Tester { void subdivideQuadratic(); void subdivideCubic(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -109,6 +112,8 @@ BezierTest::BezierTest() { &BezierTest::subdivideQuadratic, &BezierTest::subdivideCubic, + &BezierTest::strictWeakOrdering, + &BezierTest::debug, &BezierTest::configuration}); } @@ -312,6 +317,21 @@ void BezierTest::subdivideCubic() { CORRADE_COMPARE(right, (CubicBezier2D{Vector2{7.10938f, 6.57812f}, Vector2{13.4375f, 8.6875f}, Vector2{16.25f, -2.0f}, Vector2{5.0f, -20.0f}})); } +void BezierTest::strictWeakOrdering() { + StrictWeakOrdering o; + CubicBezier2D a{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, -20.0f}}; + CubicBezier2D b{Vector2{1.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, -20.0f}}; + CubicBezier2D c{Vector2{0.0f, 0.0f}, Vector2{10.0f, 15.0f}, Vector2{20.0f, 4.0f}, Vector2{5.0f, 20.0f}}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + + CORRADE_VERIFY(!o(a, a)); +} + void BezierTest::debug() { std::ostringstream out; Debug(&out) << CubicBezier2D{Vector2{0.0f, 1.0f}, Vector2{1.5f, -0.3f}, Vector2{2.1f, 0.5f}, Vector2{0.0f, 2.0f}}; diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index 275df2126..42396c960 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -27,6 +27,7 @@ #include #include "Magnum/Math/BoolVector.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct BVec3 { bool x, y, z; @@ -73,6 +74,8 @@ struct BoolVectorTest: Corrade::TestSuite::Tester { void bitInverse(); void bitAndOrXor(); + void strictWeakOrdering(); + void debug(); }; @@ -103,6 +106,8 @@ BoolVectorTest::BoolVectorTest() { &BoolVectorTest::bitInverse, &BoolVectorTest::bitAndOrXor, + &BoolVectorTest::strictWeakOrdering, + &BoolVectorTest::debug}); } @@ -290,6 +295,38 @@ void BoolVectorTest::bitAndOrXor() { CORRADE_COMPARE(a ^ b, BoolVector19(0x92, 0xac, 0x05)); } +void BoolVectorTest::strictWeakOrdering() { + BoolVector<11> a, b, c; + + a.set(0, true); + a.set(1, true); + + c.set(7, true); + + b.set(8, true); + + StrictWeakOrdering o; + CORRADE_VERIFY( o(b, a)); + CORRADE_VERIFY(!o(a, b)); + CORRADE_VERIFY(!o(c, b)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + + CORRADE_VERIFY(!o(a, a)); + + // check uninitialized padding reads + a.set(8, true); + a.set(10, true); + b = a; + a.data()[1] |= 0x08; + b.data()[1] |= 0x20; + a.data()[1] |= 0x40; + b.data()[1] |= 0x80; + + CORRADE_VERIFY(!o(a, b)); + CORRADE_VERIFY(!o(b, a)); +} + void BoolVectorTest::debug() { std::ostringstream o; diff --git a/src/Magnum/Math/Test/CMakeLists.txt b/src/Magnum/Math/Test/CMakeLists.txt index 14311a9a1..4a108f0ab 100644 --- a/src/Magnum/Math/Test/CMakeLists.txt +++ b/src/Magnum/Math/Test/CMakeLists.txt @@ -63,6 +63,8 @@ corrade_add_test(MathIntersectionBenchmark IntersectionBenchmark.cpp LIBRARIES M corrade_add_test(MathInterpolationBenchmark InterpolationBenchmark.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(MathStrictWeakOrderingTest StrictWeakOrderingTest.cpp LIBRARIES MagnumMathTestLib) + set_property(TARGET MathVectorTest MathMatrixTest @@ -110,9 +112,12 @@ set_target_properties( MathDualQuaternionTest MathBezierTest + MathCubicHermiteTest MathFrustumTest MathDistanceTest MathIntersectionTest MathIntersectionBenchmark + + MathStrictWeakOrderingTest PROPERTIES FOLDER "Magnum/Math/Test") diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index 55d9e2eb1..12bb98891 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -33,6 +33,7 @@ #endif #include "Magnum/Math/Color.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Vec3 { float x, y, z; @@ -105,6 +106,8 @@ struct ColorTest: Corrade::TestSuite::Tester { void fromXyzDefaultAlpha(); void xyY(); + void strictWeakOrdering(); + void swizzleType(); void debug(); void debugUb(); @@ -217,6 +220,8 @@ ColorTest::ColorTest() { &ColorTest::fromXyzDefaultAlpha, &ColorTest::xyY, + &ColorTest::strictWeakOrdering, + &ColorTest::swizzleType, &ColorTest::debug, &ColorTest::debugUb, @@ -850,6 +855,32 @@ void ColorTest::xyY() { CORRADE_COMPARE(xyYToXyz(xyY), xyz); } +void ColorTest::strictWeakOrdering() { + StrictWeakOrdering o; + + auto r = Color4::red(); + auto g = Color4::green(); + auto b = Color4::blue(); + + CORRADE_VERIFY( o(b, r)); + CORRADE_VERIFY( o(g, r)); + CORRADE_VERIFY( o(b, g)); + CORRADE_VERIFY(!o(r, r)); + + auto ba = b; + ba.a() = 0.5f; + CORRADE_VERIFY(o(ba, b)); + + auto r3 = r.rgb(); + auto g3 = g.rgb(); + auto b3 = b.rgb(); + + CORRADE_VERIFY( o(b3, r3)); + CORRADE_VERIFY( o(g3, r3)); + CORRADE_VERIFY( o(b3, g3)); + CORRADE_VERIFY(!o(r3, r3)); +} + void ColorTest::swizzleType() { constexpr Color3 origColor3; constexpr Color4ub origColor4; diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index 1aebdd486..cd6e24b97 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -29,6 +29,7 @@ #include "Magnum/Math/Complex.h" #include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Cmpl { float re, im; @@ -98,6 +99,8 @@ struct ComplexTest: Corrade::TestSuite::Tester { void slerpNotNormalized(); void transformVector(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -150,6 +153,8 @@ ComplexTest::ComplexTest() { &ComplexTest::slerpNotNormalized, &ComplexTest::transformVector, + &ComplexTest::strictWeakOrdering, + &ComplexTest::debug, &ComplexTest::configuration}); } @@ -529,6 +534,21 @@ void ComplexTest::transformVector() { CORRADE_COMPARE(rotated, Vector2(-3.58733f, -0.762279f)); } +void ComplexTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Complex a{1.0f, 2.0f}; + const Complex b{2.0f, 3.0f}; + const Complex c{1.0f, 3.0f}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + CORRADE_VERIFY(!o(a, a)); +} + void ComplexTest::debug() { std::ostringstream o; diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index 7a955a80f..e91bdd645 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -30,6 +30,8 @@ #include "Magnum/Math/CubicHermite.h" #include "Magnum/Math/Functions.h" #include "Magnum/Math/Vector2.h" +#include "Magnum/Math/StrictWeakOrdering.h" + namespace Magnum { namespace Math { namespace Test { @@ -112,6 +114,8 @@ struct CubicHermiteTest: Corrade::TestSuite::Tester { void splerpQuaternion(); void splerpQuaternionNotNormalized(); + void strictWeakOrdering(); + void debugScalar(); void debugVector(); void debugComplex(); @@ -195,6 +199,8 @@ CubicHermiteTest::CubicHermiteTest() { &CubicHermiteTest::splerpQuaternion, &CubicHermiteTest::splerpQuaternionNotNormalized, + &CubicHermiteTest::strictWeakOrdering, + &CubicHermiteTest::debugScalar, &CubicHermiteTest::debugVector, &CubicHermiteTest::debugComplex, @@ -1129,6 +1135,25 @@ void CubicHermiteTest::splerpQuaternionNotNormalized() { "Math::splerp(): quaternion spline points Quaternion({0, 0, 0}, 2) and Quaternion({0, 0, 0}, 1) are not normalized\n"); } +void CubicHermiteTest::strictWeakOrdering() { + StrictWeakOrdering o; + const CubicHermite1D a{1.0f, 2.0f, 3.0f}; + const CubicHermite1D b{2.0f, 3.0f, 4.0f}; + const CubicHermite1D c{1.0f, 2.0f, 4.0f}; + const CubicHermite1D d{1.0f, 5.0f, 4.0f}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + CORRADE_VERIFY( o(a, d)); + CORRADE_VERIFY(!o(d, a)); + + CORRADE_VERIFY(!o(a, a)); +} + void CubicHermiteTest::debugScalar() { std::ostringstream out; Debug{&out} << CubicHermite1D{2.0f, 3.0f, -1.0f}; diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 6fd4e78b1..3e44fa5d9 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -29,6 +29,7 @@ #include "Magnum/Math/DualComplex.h" #include "Magnum/Math/DualQuaternion.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct DualCmpl { float re, im, x, y; @@ -91,6 +92,8 @@ struct DualComplexTest: Corrade::TestSuite::Tester { void matrixNotOrthogonal(); void transformPoint(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -147,6 +150,8 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::matrixNotOrthogonal, &DualComplexTest::transformPoint, + &DualComplexTest::strictWeakOrdering, + &DualComplexTest::debug, &DualComplexTest::configuration}); } @@ -445,6 +450,21 @@ void DualComplexTest::transformPoint() { CORRADE_COMPARE(transformedB, Vector2(-2.918512f, 2.780698f)); } +void DualComplexTest::strictWeakOrdering() { + StrictWeakOrdering o; + const DualComplex a{{1.0f, 0.0f}, {1.0f, 3.0f}}; + const DualComplex b{{1.0f, 2.0f}, {3.0f, 4.0f}}; + const DualComplex c{{1.0f, 0.0f}, {1.0f, 4.0f}}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + CORRADE_VERIFY(!o(a, a)); +} + void DualComplexTest::debug() { std::ostringstream o; diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 9aceedcba..c2cf3384a 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/DualQuaternion.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct DualQuat { struct { float x, y, z, w; } re; @@ -98,6 +99,8 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester { void sclerp(); void sclerpShortestPath(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -159,6 +162,8 @@ DualQuaternionTest::DualQuaternionTest() { &DualQuaternionTest::sclerp, &DualQuaternionTest::sclerpShortestPath, + &DualQuaternionTest::strictWeakOrdering, + &DualQuaternionTest::debug, &DualQuaternionTest::configuration}); } @@ -620,6 +625,21 @@ void DualQuaternionTest::sclerpShortestPath() { CORRADE_COMPARE(sclerpShortestPath.translation().z(), 0.25f); } +void DualQuaternionTest::strictWeakOrdering() { + StrictWeakOrdering o; + const DualQuaternion a{{{1.0f, 2.0f, 3.0f}, 0.0f}, {{1.0f, 2.0f, 3.0f}, 3.0f}}; + const DualQuaternion b{{{1.0f, 2.0f, 3.0f}, 2.0f}, {{3.0f, 2.0f, 3.0f}, 4.0f}}; + const DualQuaternion c{{{1.0f, 2.0f, 3.0f}, 0.0f}, {{1.0f, 2.0f, 3.0f}, 4.0f}}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + CORRADE_VERIFY(!o(a, a)); +} + void DualQuaternionTest::debug() { std::ostringstream o; diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index 557d3d157..94f7010d3 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -29,6 +29,7 @@ #include "Magnum/Math/Dual.h" #include "Magnum/Math/Quaternion.h" #include "Magnum/Math/Vector2.h" +#include "Magnum/Math/StrictWeakOrdering.h" namespace Magnum { namespace Math { namespace Test { @@ -58,6 +59,8 @@ struct DualTest: Corrade::TestSuite::Tester { void sincos(); void sincosWithBase(); + void strictWeakOrdering(); + void subclassTypes(); void subclass(); @@ -97,6 +100,8 @@ DualTest::DualTest() { &DualTest::sincos, &DualTest::sincosWithBase, + &DualTest::strictWeakOrdering, + &DualTest::subclassTypes, &DualTest::subclass, @@ -278,6 +283,21 @@ void DualTest::sincosWithBase() { CORRADE_COMPARE(Math::sincos(2*Math::Dual(Rad(Constants::pi()/12), Rad(Constants::pi()/4))), result); } +void DualTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Dual a{1.0f, 2.0f}; + const Dual b{2.0f, 3.0f}; + const Dual c{1.0f, 3.0f}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + CORRADE_VERIFY(!o(a, a)); +} + namespace { template class BasicDualVec2: public Math::Dual> { diff --git a/src/Magnum/Math/Test/HalfTest.cpp b/src/Magnum/Math/Test/HalfTest.cpp index bb3e43684..2c841aa67 100644 --- a/src/Magnum/Math/Test/HalfTest.cpp +++ b/src/Magnum/Math/Test/HalfTest.cpp @@ -33,6 +33,7 @@ #include "Magnum/Math/Half.h" #include "Magnum/Math/Vector3.h" +#include "Magnum/Math/StrictWeakOrdering.h" namespace Magnum { namespace Math { namespace Test { @@ -62,6 +63,8 @@ struct HalfTest: Corrade::TestSuite::Tester { void promotion(); void negation(); + void strictWeakOrdering(); + void literal(); void debug(); #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) @@ -153,6 +156,8 @@ HalfTest::HalfTest() { addTests({&HalfTest::promotion, &HalfTest::negation, + &HalfTest::strictWeakOrdering, + &HalfTest::literal, &HalfTest::debug}); @@ -651,6 +656,16 @@ void HalfTest::negation() { CORRADE_COMPARE(-b, a); } +void HalfTest::strictWeakOrdering() { + StrictWeakOrdering o; + constexpr Half a{UnsignedShort(0x4300)}; + constexpr Half b{UnsignedShort(0x5100)}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY(!o(a, a)); +} + void HalfTest::literal() { Half a = 3.5_h; CORRADE_COMPARE(a, Half{UnsignedShort(0x4300)}); diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index 225217490..358ba5bf7 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Matrix3.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Mat3 { float a[9]; @@ -96,6 +97,8 @@ struct Matrix3Test: Corrade::TestSuite::Tester { void invertedRigidNotRigid(); void transform(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -145,6 +148,8 @@ Matrix3Test::Matrix3Test() { &Matrix3Test::invertedRigidNotRigid, &Matrix3Test::transform, + &Matrix3Test::strictWeakOrdering, + &Matrix3Test::debug, &Matrix3Test::configuration}); } @@ -592,6 +597,22 @@ void Matrix3Test::transform() { CORRADE_COMPARE(a.transformPoint(v), Vector2(3.0f, -4.0f)); } +void Matrix3Test::strictWeakOrdering() { + StrictWeakOrdering o; + const Matrix3 a(Vector3{1.0f, 1.0f, 2.0f}, Vector3{5.0f, 5.0f, 5.0f}, Vector3{3.0f, 1.0f, 4.0f}); + const Matrix3 b(Vector3{2.0f, 1.0f, 3.0f}, Vector3{5.0f, 5.0f, 5.0f}, Vector3{4.0f, 1.0f, 5.0f}); + const Matrix3 c(Vector3{1.0f, 1.0f, 2.0f}, Vector3{5.0f, 5.0f, 5.0f}, Vector3{3.0f, 1.0f, 5.0f}); + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + void Matrix3Test::debug() { Matrix3 m({3.0f, 5.0f, 8.0f}, {4.0f, 4.0f, 7.0f}, diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index aab4cb787..4f369eaee 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -29,6 +29,7 @@ #include #include "Magnum/Math/Matrix4.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Mat4 { float a[16]; @@ -110,6 +111,8 @@ struct Matrix4Test: Corrade::TestSuite::Tester { void transform(); void transformProjection(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -174,6 +177,8 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::transform, &Matrix4Test::transformProjection, + &Matrix4Test::strictWeakOrdering, + &Matrix4Test::debug, &Matrix4Test::configuration}); } @@ -770,6 +775,22 @@ void Matrix4Test::transformProjection() { CORRADE_COMPARE(a.transformPoint(v), Vector3(0.0f, 0.0f, 1.0f)); } +void Matrix4Test::strictWeakOrdering() { + StrictWeakOrdering o; + const Matrix4 a(Vector4{1.0f, 1.0f, 2.0f, 2.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{3.0f, 1.0f, 2.0f, 4.0f}); + const Matrix4 b(Vector4{2.0f, 1.0f, 2.0f, 3.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{4.0f, 1.0f, 2.0f, 5.0f}); + const Matrix4 c(Vector4{1.0f, 1.0f, 2.0f, 2.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{5.0f, 5.0f, 6.0f, 5.0f}, Vector4{3.0f, 1.0f, 2.0f, 5.0f}); + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + void Matrix4Test::lookAt() { Vector3 translation{5.3f, -8.9f, -10.0f}; Vector3 target{19.0f, 29.3f, 0.0f}; diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index f1ddb5c2e..9f580df3e 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Matrix.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Mat3 { float a[9]; @@ -79,6 +80,8 @@ struct MatrixTest: Corrade::TestSuite::Tester { void invertedOrthogonal(); void invertedOrthogonalNotOrthogonal(); + void strictWeakOrdering(); + void subclassTypes(); void subclass(); @@ -117,6 +120,8 @@ MatrixTest::MatrixTest() { &MatrixTest::invertedOrthogonal, &MatrixTest::invertedOrthogonalNotOrthogonal, + &MatrixTest::strictWeakOrdering, + &MatrixTest::subclassTypes, &MatrixTest::subclass, @@ -385,6 +390,22 @@ void MatrixTest::invertedOrthogonalNotOrthogonal() { " 0, 0, 2)\n"); } +void MatrixTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Matrix2x2 a{Vector2{1.0f, 2.0f}, Vector2{3.0f, 4.0f}}; + const Matrix2x2 b{Vector2{2.0f, 3.0f}, Vector2{4.0f, 5.0f}}; + const Matrix2x2 c{Vector2{1.0f, 2.0f}, Vector2{3.0f, 5.0f}}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + template class BasicVec2: public Math::Vector<2, T> { public: template constexpr BasicVec2(U&&... args): Math::Vector<2, T>{args...} {} diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index 946e0d6c5..5f7990a56 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -30,6 +30,7 @@ #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Quaternion.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Quat { float x, y, z, w; @@ -111,6 +112,8 @@ struct QuaternionTest: Corrade::TestSuite::Tester { void transformVectorNormalized(); void transformVectorNormalizedNotNormalized(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -185,6 +188,8 @@ QuaternionTest::QuaternionTest() { &QuaternionTest::transformVectorNormalized, &QuaternionTest::transformVectorNormalizedNotNormalized, + &QuaternionTest::strictWeakOrdering, + &QuaternionTest::debug, &QuaternionTest::configuration}); } @@ -716,6 +721,22 @@ void QuaternionTest::transformVectorNormalizedNotNormalized() { CORRADE_COMPARE(out.str(), "Math::Quaternion::transformVectorNormalized(): Quaternion({0.398736, 0, 0}, 1.95985) is not normalized\n"); } +void QuaternionTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Quaternion a{{1.0f, 2.0f, 3.0f}, 4.0f}; + const Quaternion b{{2.0f, 3.0f, 4.0f}, 5.0f}; + const Quaternion c{{1.0f, 2.0f, 3.0f}, 5.0f}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + void QuaternionTest::debug() { std::ostringstream o; diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index 946af47a1..66fc8575d 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Range.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Dim { float offset, size; @@ -134,6 +135,8 @@ struct RangeTest: Corrade::TestSuite::Tester { void join(); void join1D(); + void strictWeakOrdering(); + void subclassTypes(); void subclass(); @@ -185,6 +188,8 @@ RangeTest::RangeTest() { &RangeTest::join, &RangeTest::join1D, + &RangeTest::strictWeakOrdering, + &RangeTest::subclassTypes, &RangeTest::subclass, @@ -824,6 +829,22 @@ void RangeTest::join1D() { CORRADE_COMPARE(Math::join(c, a), a); } +void RangeTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Range1D a{1.0f, 2.0f}; + const Range1D b{2.0f, 3.0f}; + const Range1D c{1.0f, 3.0f}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + template class BasicRect: public Math::Range<2, T> { public: template constexpr BasicRect(U&&... args): Math::Range<2, T>{args...} {} diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index dcae814b0..b17a979a6 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/RectangularMatrix.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Mat2x3 { float a[6]; @@ -90,6 +91,8 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { void subclassTypes(); void subclass(); + void strictWeakOrdering(); + void debug(); void configuration(); }; @@ -142,6 +145,8 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::subclassTypes, &RectangularMatrixTest::subclass, + &RectangularMatrixTest::strictWeakOrdering, + &RectangularMatrixTest::debug, &RectangularMatrixTest::configuration}); } @@ -674,6 +679,22 @@ void RectangularMatrixTest::subclass() { Vector2{-2.0f, 7.0f}})); } +void RectangularMatrixTest::strictWeakOrdering() { + StrictWeakOrdering o; + const Matrix2x2 a{Vector2{1.0f, 2.0f}, Vector2{3.0f, 4.0f}}; + const Matrix2x2 b{Vector2{2.0f, 3.0f}, Vector2{4.0f, 5.0f}}; + const Matrix2x2 c{Vector2{1.0f, 2.0f}, Vector2{3.0f, 5.0f}}; + + CORRADE_VERIFY( o(a, b)); + CORRADE_VERIFY(!o(b, a)); + CORRADE_VERIFY( o(a, c)); + CORRADE_VERIFY(!o(c, a)); + CORRADE_VERIFY( o(c, b)); + CORRADE_VERIFY(!o(b, c)); + + CORRADE_VERIFY(!o(a, a)); +} + void RectangularMatrixTest::debug() { Matrix3x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f), Vector4(4.0f, 4.0f, 7.0f, 3.0f), diff --git a/src/Magnum/Math/Test/StrictWeakOrderingTest.cpp b/src/Magnum/Math/Test/StrictWeakOrderingTest.cpp new file mode 100644 index 000000000..9d5eb6ccb --- /dev/null +++ b/src/Magnum/Math/Test/StrictWeakOrderingTest.cpp @@ -0,0 +1,178 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include + +#include "Magnum/Math/Vector2.h" +#include "Magnum/Math/StrictWeakOrdering.h" + +namespace std +{ + template <> struct less> + : public Magnum::Math::Implementation::StrictWeakOrdering> + {}; +} + +namespace Magnum { +namespace Math { + +namespace Test { + +using Vector2 = Magnum::Math::Vector2; + +struct StrictWeakOrderingTest : Corrade::TestSuite::Tester { + explicit StrictWeakOrderingTest(); + + void base(); + + void set(); + void setShort(); + void setLess(); + + void map(); + void mapShort(); + void mapLess(); + +}; + +StrictWeakOrderingTest::StrictWeakOrderingTest() { + addTests({ &StrictWeakOrderingTest::base, + + &StrictWeakOrderingTest::set, + &StrictWeakOrderingTest::setShort, + &StrictWeakOrderingTest::setLess, + + &StrictWeakOrderingTest::map, + &StrictWeakOrderingTest::mapShort, + &StrictWeakOrderingTest::mapLess}); +} + +void StrictWeakOrderingTest::base() { + Implementation::StrictWeakOrdering o; + CORRADE_VERIFY(o(1, 2)); + CORRADE_VERIFY(!o(2, 2)); + CORRADE_VERIFY(!o(3, 2)); + + StrictWeakOrdering of; + CORRADE_VERIFY(of(1, 2)); + CORRADE_VERIFY(!of(2.5, 2.5)); + CORRADE_VERIFY(!of('z', 'h')); +} + +void StrictWeakOrderingTest::set() { + std::set> s; + + s.insert({1, 2}); + s.insert({2, 3}); + + CORRADE_VERIFY(s.size() == 2); + CORRADE_VERIFY(*s.begin() == Vector2(1, 2)); + CORRADE_VERIFY(*s.rbegin() == Vector2(2, 3)); + + s.insert({1, 2}); + CORRADE_VERIFY(s.size() == 2); +} + +void StrictWeakOrderingTest::setShort() { + std::set s; + + s.insert({1, 2}); + s.insert({2, 3}); + + CORRADE_VERIFY(s.size() == 2); + CORRADE_VERIFY(*s.begin() == Vector2(1, 2)); + CORRADE_VERIFY(*s.rbegin() == Vector2(2, 3)); + + s.insert({1, 2}); + CORRADE_VERIFY(s.size() == 2); +} + +void StrictWeakOrderingTest::setLess() { + std::set s; + + s.insert({1, 2}); + s.insert({2, 3}); + + CORRADE_VERIFY(s.size() == 2); + CORRADE_VERIFY(*s.begin() == Vector2(1, 2)); + CORRADE_VERIFY(*s.rbegin() == Vector2(2, 3)); + + s.insert({1, 2}); + CORRADE_VERIFY(s.size() == 2); +} + +void StrictWeakOrderingTest::map() { + std::map> m; + + m[Vector2{1, 2}] = 23; + m[Vector2{4, 5}] = 55; + + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 23); + CORRADE_VERIFY(m.rbegin()->second == 55); + + m[Vector2{1, 2}] = 99; + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 99); +} + +void StrictWeakOrderingTest::mapShort() { + std::map m; + + m[Vector2{1, 2}] = 23; + m[Vector2{4, 5}] = 55; + + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 23); + CORRADE_VERIFY(m.rbegin()->second == 55); + + m[Vector2{1, 2}] = 99; + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 99); +} + +void StrictWeakOrderingTest::mapLess() { + std::map m; + + m[Vector2{1, 2}] = 23; + m[Vector2{4, 5}] = 55; + + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 23); + CORRADE_VERIFY(m.rbegin()->second == 55); + + m[Vector2{1, 2}] = 99; + CORRADE_VERIFY(m.size() == 2); + CORRADE_VERIFY(m.begin()->second == 99); +} + +} +} +} + +CORRADE_TEST_MAIN(Magnum::Math::Test::StrictWeakOrderingTest) diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index f39dc11ac..f7a355c22 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Vector3.h" /* Vector3 used in Vector2Test::cross() */ +#include "Magnum/Math/StrictWeakOrdering.h" struct Vec2 { float x, y; @@ -69,6 +70,8 @@ struct Vector2Test: Corrade::TestSuite::Tester { void perpendicular(); void aspectRatio(); + void strictWeakOrdering(); + void swizzleType(); void debug(); void configuration(); @@ -94,6 +97,8 @@ Vector2Test::Vector2Test() { &Vector2Test::perpendicular, &Vector2Test::aspectRatio, + &Vector2Test::strictWeakOrdering, + &Vector2Test::swizzleType, &Vector2Test::debug, &Vector2Test::configuration}); @@ -226,6 +231,22 @@ void Vector2Test::aspectRatio() { CORRADE_COMPARE(Vector2(3.0f, 4.0f).aspectRatio(), 0.75f); } +void Vector2Test::strictWeakOrdering() { + StrictWeakOrdering o; + const Vector2 v2a{1.0f, 2.0f}; + const Vector2 v2b{2.0f, 3.0f}; + const Vector2 v2c{1.0f, 3.0f}; + + CORRADE_VERIFY( o(v2a, v2b)); + CORRADE_VERIFY(!o(v2b, v2a)); + CORRADE_VERIFY( o(v2a, v2c)); + CORRADE_VERIFY(!o(v2c, v2a)); + CORRADE_VERIFY( o(v2c, v2b)); + CORRADE_VERIFY(!o(v2b, v2c)); + + CORRADE_VERIFY(!o(v2a, v2a)); +} + void Vector2Test::swizzleType() { constexpr Vector<4, Int> orig; constexpr auto a = swizzle<'y', 'a'>(orig); diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index f716d9526..46e1d3510 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Vector3.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Vec3 { float x, y, z; @@ -69,6 +70,8 @@ struct Vector3Test: Corrade::TestSuite::Tester { void scales(); void twoComponent(); + void strictWeakOrdering(); + void swizzleType(); void debug(); void configuration(); @@ -94,6 +97,8 @@ Vector3Test::Vector3Test() { &Vector3Test::scales, &Vector3Test::twoComponent, + &Vector3Test::strictWeakOrdering, + &Vector3Test::swizzleType, &Vector3Test::debug, &Vector3Test::configuration}); @@ -250,6 +255,22 @@ void Vector3Test::twoComponent() { CORRADE_COMPARE(d, 2.0f); } +void Vector3Test::strictWeakOrdering() { + StrictWeakOrdering o; + const Vector3 v3a{1.0f, 2.0f, 3.0f}; + const Vector3 v3b{2.0f, 3.0f, 4.0f}; + const Vector3 v3c{1.0f, 2.0f, 4.0f}; + + CORRADE_VERIFY( o(v3a, v3b)); + CORRADE_VERIFY(!o(v3b, v3a)); + CORRADE_VERIFY( o(v3a, v3c)); + CORRADE_VERIFY(!o(v3c, v3a)); + CORRADE_VERIFY( o(v3c, v3b)); + CORRADE_VERIFY(!o(v3b, v3c)); + + CORRADE_VERIFY(!o(v3a, v3a)); +} + void Vector3Test::swizzleType() { constexpr Vector<4, Int> orig; constexpr auto b = swizzle<'y', 'z', 'a'>(orig); diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index 51a2d4057..dde7c315b 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Vector4.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Vec4 { float x, y, z, w; @@ -71,6 +72,8 @@ struct Vector4Test: Corrade::TestSuite::Tester { void planeEquationThreePoints(); void planeEquationNormalPoint(); + void strictWeakOrdering(); + void swizzleType(); void debug(); void configuration(); @@ -99,6 +102,8 @@ Vector4Test::Vector4Test() { &Vector4Test::planeEquationThreePoints, &Vector4Test::planeEquationNormalPoint, + &Vector4Test::strictWeakOrdering, + &Vector4Test::swizzleType, &Vector4Test::debug, &Vector4Test::configuration}); @@ -293,6 +298,22 @@ void Vector4Test::planeEquationNormalPoint() { CORRADE_COMPARE(eq, (Vector4{-0.9045340f, 0.3015113f, -0.3015113f, 1.658312f})); } +void Vector4Test::strictWeakOrdering() { + StrictWeakOrdering o; + const Vector4 v4a{1.0f, 2.0f, 3.0f, 4.0f}; + const Vector4 v4b{2.0f, 3.0f, 4.0f, 5.0f}; + const Vector4 v4c{1.0f, 2.0f, 3.0f, 5.0f}; + + CORRADE_VERIFY( o(v4a, v4b)); + CORRADE_VERIFY(!o(v4b, v4a)); + CORRADE_VERIFY( o(v4a, v4c)); + CORRADE_VERIFY(!o(v4c, v4a)); + CORRADE_VERIFY( o(v4c, v4b)); + CORRADE_VERIFY(!o(v4b, v4c)); + + CORRADE_VERIFY(!o(v4a, v4a)); +} + void Vector4Test::swizzleType() { constexpr Vector4i orig; constexpr auto c = swizzle<'y', 'a', 'y', 'x'>(orig); diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 78bd118fd..445565d24 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -28,6 +28,7 @@ #include #include "Magnum/Math/Vector.h" +#include "Magnum/Math/StrictWeakOrdering.h" struct Vec3 { float x, y, z; @@ -107,11 +108,14 @@ struct VectorTest: Corrade::TestSuite::Tester { void subclassTypes(); void subclass(); + void strictWeakOrdering(); + void debug(); void configuration(); }; typedef Math::Rad Rad; +typedef Vector<2, Float> Vector2; typedef Vector<3, Float> Vector3; typedef Vector<4, Float> Vector4; typedef Vector<4, Int> Vector4i; @@ -170,6 +174,8 @@ VectorTest::VectorTest() { &VectorTest::subclassTypes, &VectorTest::subclass, + &VectorTest::strictWeakOrdering, + &VectorTest::debug, &VectorTest::configuration}); } @@ -695,6 +701,49 @@ void VectorTest::subclass() { CORRADE_COMPARE(flipped, (Vec2{0.4f, 1.0f})); } +void VectorTest::strictWeakOrdering() { + StrictWeakOrdering o; + + const Vector2 v2a{1.0f, 2.0f}; + const Vector2 v2b{2.0f, 3.0f}; + const Vector2 v2c{1.0f, 3.0f}; + + CORRADE_VERIFY( o(v2a, v2b)); + CORRADE_VERIFY(!o(v2b, v2a)); + CORRADE_VERIFY( o(v2a, v2c)); + CORRADE_VERIFY(!o(v2c, v2a)); + CORRADE_VERIFY( o(v2c, v2b)); + CORRADE_VERIFY(!o(v2b, v2c)); + + CORRADE_VERIFY(!o(v2a, v2a)); + + const Vector3 v3a{1.0f, 2.0f, 3.0f}; + const Vector3 v3b{2.0f, 3.0f, 4.0f}; + const Vector3 v3c{1.0f, 2.0f, 4.0f}; + + CORRADE_VERIFY( o(v3a, v3b)); + CORRADE_VERIFY(!o(v3b, v3a)); + CORRADE_VERIFY( o(v3a, v3c)); + CORRADE_VERIFY(!o(v3c, v3a)); + CORRADE_VERIFY( o(v3c, v3b)); + CORRADE_VERIFY(!o(v3b, v3c)); + + CORRADE_VERIFY(!o(v3a, v3a)); + + const Vector4 v4a{1.0f, 2.0f, 3.0f, 4.0f}; + const Vector4 v4b{2.0f, 3.0f, 4.0f, 5.0f}; + const Vector4 v4c{1.0f, 2.0f, 3.0f, 5.0f}; + + CORRADE_VERIFY( o(v4a, v4b)); + CORRADE_VERIFY(!o(v4b, v4a)); + CORRADE_VERIFY( o(v4a, v4c)); + CORRADE_VERIFY(!o(v4c, v4a)); + CORRADE_VERIFY( o(v4c, v4b)); + CORRADE_VERIFY(!o(v4b, v4c)); + + CORRADE_VERIFY(!o(v4a, v4a)); +} + void VectorTest::debug() { std::ostringstream o; Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 28a14a558..0a98ba2ca 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -1413,6 +1413,22 @@ template inline std::pair Vector::minm return {min, max}; } +/* Specialization of helper types*/ +namespace Implementation { +template struct StrictWeakOrdering> { + bool operator()(const Vector& a, const Vector& b) const { + for(std::size_t i = 0; i < size; ++i) { + if(a[i] < b[i]) + return true; + if(a[i] > b[i]) + return false; + } + + return false; // a and b are equivalent + } +}; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index 1f33fb91a..c09b2d2ce 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -190,6 +190,8 @@ MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(2, Vector2) namespace Implementation { template struct TypeForSize; template struct TypeForSize<2, T> { typedef Math::Vector2 Type; }; + + template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; } }} diff --git a/src/Magnum/Math/Vector3.h b/src/Magnum/Math/Vector3.h index 4ae6468f6..03da92c70 100644 --- a/src/Magnum/Math/Vector3.h +++ b/src/Magnum/Math/Vector3.h @@ -245,6 +245,8 @@ MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, Vector3) namespace Implementation { template struct TypeForSize<3, T> { typedef Math::Vector3 Type; }; + + template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; } }} diff --git a/src/Magnum/Math/Vector4.h b/src/Magnum/Math/Vector4.h index 56d6751d9..92c81ed16 100644 --- a/src/Magnum/Math/Vector4.h +++ b/src/Magnum/Math/Vector4.h @@ -254,6 +254,8 @@ MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, Vector4) namespace Implementation { template struct TypeForSize<4, T> { typedef Math::Vector4 Type; }; + + template struct StrictWeakOrdering>: public StrictWeakOrdering> {}; } }}