Browse Source

Math: added minmax() and Vector2::minmax().

No Vector<size, T> and std::initializer_list versions yet, as the
algorithm for it is pretty complicated and I'm not sure that they will
be used frequently enough to deserve their existence.
pull/34/head
Vladimír Vondruš 13 years ago
parent
commit
4059bd752f
  1. 26
      src/Math/Functions.h
  2. 14
      src/Math/Test/FunctionsTest.cpp
  3. 8
      src/Math/Test/Vector2Test.cpp
  4. 4
      src/Math/Vector.h
  5. 9
      src/Math/Vector2.h

26
src/Math/Functions.h

@ -25,8 +25,9 @@
*/ */
#include <cmath> #include <cmath>
#include <type_traits>
#include <limits> #include <limits>
#include <type_traits>
#include <utility>
#include "Math/Vector.h" #include "Math/Vector.h"
@ -124,7 +125,7 @@ perform the operations component-wise.
/** /**
@brief Minimum @brief Minimum
@see min(), clamp(), Vector::min() @see @ref max(), @ref minmax(), @ref clamp(), @ref Vector::min()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T min(T a, T b); template<class T> inline T min(T a, T b);
@ -151,7 +152,7 @@ template<class T> inline T min(std::initializer_list<T> list) {
/** /**
@brief Maximum @brief Maximum
@see max(), clamp(), Vector::max() @see @ref min(), @ref minmax(), @ref clamp(), @ref Vector::max()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T max(const T& a, const T& b); template<class T> inline T max(const T& a, const T& b);
@ -175,6 +176,25 @@ template<class T> inline T max(std::initializer_list<T> list) {
return out; return out;
} }
/**
@brief Minimum and maximum of two values
@see @ref min(), @ref max(), @ref clamp(), @ref Vector2::minmax()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline std::pair<T, T> minmax(const T& a, const T& b);
#else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, std::pair<T, T>>::type minmax(T a, T b) {
return a < b ? std::make_pair(a, b) : std::make_pair(b, a);
}
template<std::size_t size, class T> std::pair<Vector<size, T>, Vector<size, T>> minmax(const Vector<size, T>& a, const Vector<size, T>& b) {
std::pair<Vector<size, T>, Vector<size, T>> out{a, b};
for(std::size_t i = 0; i != size; ++i)
if(out.first[i] > out.second[i]) std::swap(out.first[i], out.second[i]);
return out;
}
#endif
/** /**
@brief Sign @brief Sign

14
src/Math/Test/FunctionsTest.cpp

@ -37,6 +37,7 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
void minList(); void minList();
void max(); void max();
void maxList(); void maxList();
void minmax();
void sign(); void sign();
void abs(); void abs();
@ -79,6 +80,7 @@ FunctionsTest::FunctionsTest() {
&FunctionsTest::minList, &FunctionsTest::minList,
&FunctionsTest::max, &FunctionsTest::max,
&FunctionsTest::maxList, &FunctionsTest::maxList,
&FunctionsTest::minmax,
&FunctionsTest::sign, &FunctionsTest::sign,
&FunctionsTest::abs, &FunctionsTest::abs,
@ -132,6 +134,18 @@ void FunctionsTest::maxList() {
Vector3i(9, -5, 18)}), Vector3i(9, 14, 18)); Vector3i(9, -5, 18)}), Vector3i(9, 14, 18));
} }
void FunctionsTest::minmax() {
const auto expectedScalar = std::make_pair(-5.0f, 4.0f);
CORRADE_COMPARE(Math::minmax(-5.0f, 4.0f), expectedScalar);
CORRADE_COMPARE(Math::minmax(4.0f, -5.0f), expectedScalar);
const Vector3 a(5.0f, -4.0f, 1.0f);
const Vector3 b(7.0f, -3.0f, 1.0f);
const std::pair<Vector3, Vector3> expectedVector{{5.0f, -4.0f, 1.0f}, {7.0f, -3.0f, 1.0f}};
CORRADE_COMPARE_AS(Math::minmax(a, b), expectedVector, std::pair<Vector3, Vector3>);
CORRADE_COMPARE_AS(Math::minmax(b, a), expectedVector, std::pair<Vector3, Vector3>);
}
void FunctionsTest::sign() { void FunctionsTest::sign() {
CORRADE_COMPARE(Math::sign(3516), 1); CORRADE_COMPARE(Math::sign(3516), 1);
CORRADE_COMPARE(Math::sign(0.0f), 0.0f); CORRADE_COMPARE(Math::sign(0.0f), 0.0f);

8
src/Math/Test/Vector2Test.cpp

@ -68,6 +68,7 @@ class Vector2Test: public Corrade::TestSuite::Tester {
void scales(); void scales();
void perpendicular(); void perpendicular();
void aspectRatio(); void aspectRatio();
void minmax();
void swizzleType(); void swizzleType();
void debug(); void debug();
@ -93,6 +94,7 @@ Vector2Test::Vector2Test() {
&Vector2Test::scales, &Vector2Test::scales,
&Vector2Test::perpendicular, &Vector2Test::perpendicular,
&Vector2Test::aspectRatio, &Vector2Test::aspectRatio,
&Vector2Test::minmax,
&Vector2Test::swizzleType, &Vector2Test::swizzleType,
&Vector2Test::debug, &Vector2Test::debug,
@ -202,6 +204,12 @@ void Vector2Test::aspectRatio() {
CORRADE_COMPARE(Vector2(3.0f, 4.0f).aspectRatio(), 0.75f); CORRADE_COMPARE(Vector2(3.0f, 4.0f).aspectRatio(), 0.75f);
} }
void Vector2Test::minmax() {
const auto expected = std::make_pair(-5.0f, 4.0f);
CORRADE_COMPARE(Vector2(-5.0f, 4.0f).minmax(), expected);
CORRADE_COMPARE(Vector2(4.0f, -5.0f).minmax(), expected);
}
void Vector2Test::swizzleType() { void Vector2Test::swizzleType() {
constexpr Vector<4, Int> orig; constexpr Vector<4, Int> orig;
constexpr auto a = swizzle<'y', 'a'>(orig); constexpr auto a = swizzle<'y', 'a'>(orig);

4
src/Math/Vector.h

@ -514,14 +514,14 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Minimal value in the vector * @brief Minimal value in the vector
* *
* @see Math::min() * @see @ref Math::min(), @ref Vector2::minmax()
*/ */
T min() const; T min() const;
/** /**
* @brief Maximal value in the vector * @brief Maximal value in the vector
* *
* @see Math::max() * @see @ref Math::max(), @ref Vector2::minmax()
*/ */
T max() const; T max() const;

9
src/Math/Vector2.h

@ -143,6 +143,15 @@ template<class T> class Vector2: public Vector<2, T> {
*/ */
T aspectRatio() const { return x()/y(); } T aspectRatio() const { return x()/y(); }
/**
* @brief Minimum and maximum value
*
* @see @ref min(), @ref max(), @ref Math::minmax()
*/
std::pair<T, T> minmax() const {
return x() < y() ? std::make_pair(x(), y()) : std::make_pair(y(), x());
}
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2) MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2)
}; };

Loading…
Cancel
Save