Browse Source

Split out lightweight base of swizzle() function to Math namespace.

Will make use of SIMD instructions and can be used elsewhere in Math.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
ef779e50b2
  1. 1
      src/Math/CMakeLists.txt
  2. 74
      src/Math/Swizzle.h
  3. 2
      src/Math/Test/CMakeLists.txt
  4. 49
      src/Math/Test/SwizzleTest.cpp
  5. 33
      src/Math/Test/SwizzleTest.h
  6. 30
      src/Swizzle.h
  7. 17
      src/Test/SwizzleTest.cpp
  8. 3
      src/Test/SwizzleTest.h

1
src/Math/CMakeLists.txt

@ -10,6 +10,7 @@ set(MagnumMath_HEADERS
Point2D.h
Point3D.h
RectangularMatrix.h
Swizzle.h
Vector.h
Vector2.h
Vector3.h

74
src/Math/Swizzle.h

@ -0,0 +1,74 @@
#ifndef Magnum_Math_Swizzle_h
#define Magnum_Math_Swizzle_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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 Function Magnum::Math::swizzle()
*/
#include "Vector.h"
namespace Magnum { namespace Math {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<std::size_t size, std::size_t position> struct ComponentAtPosition {
static_assert(size > position, "Swizzle parameter out of range of base vector");
template<class T> inline constexpr static T value(const Math::Vector<size, T>& vector) { return vector[position]; }
};
template<std::size_t size, char component> struct Component {};
template<std::size_t size> struct Component<size, 'x'>: public ComponentAtPosition<size, 0> {};
template<std::size_t size> struct Component<size, 'y'>: public ComponentAtPosition<size, 1> {};
template<std::size_t size> struct Component<size, 'z'>: public ComponentAtPosition<size, 2> {};
template<std::size_t size> struct Component<size, 'w'>: public ComponentAtPosition<size, 3> {};
template<std::size_t size> struct Component<size, '0'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(0); }
};
template<std::size_t size> struct Component<size, '1'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(1); }
};
}
#endif
/**
@brief Swizzle Vector components
Creates new vector from given components. Example:
@code
Vector4<std::int32_t> original(-1, 2, 3, 4);
auto vec = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original);
// vec == { 4, 1, 0, -1, 2, 3 }
@endcode
You can use letters `x`, `y`, `z`, `w` for addressing components or letters
`0` and `1` for zero and one. Count of elements is unlimited, but must be at
least one.
See also Magnum::swizzle() which has some added convenience features not
present in this lightweight implementation for Math namespace.
@see @ref matrix-vector-component-access, Vector4::xyz(),
Vector4::xy(), Vector3::xy()
*/
template<char ...components, std::size_t size, class T> inline constexpr Vector<sizeof...(components), T> swizzle(const Vector<size, T>& vector) {
return {Implementation::Component<size, components>::value(vector)...};
}
}}
#endif

2
src/Math/Test/CMakeLists.txt

@ -16,4 +16,6 @@ corrade_add_test(MathMatrixTest MatrixTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathMatrix3Test Matrix3Test.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
set_target_properties(MathVectorTest MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

49
src/Math/Test/SwizzleTest.cpp

@ -0,0 +1,49 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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 "SwizzleTest.h"
#include "Math/Swizzle.h"
CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleTest)
namespace Magnum { namespace Math { namespace Test {
typedef Vector<4, std::int32_t> Vector4i;
SwizzleTest::SwizzleTest() {
addTests(&SwizzleTest::components,
&SwizzleTest::constants,
&SwizzleTest::sizes);
}
void SwizzleTest::components() {
CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4));
}
void SwizzleTest::constants() {
CORRADE_COMPARE((swizzle<'1', 'w', '0', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(1, 7, 0, 4));
}
void SwizzleTest::sizes() {
CORRADE_COMPARE((swizzle<'y', 'x', 'x'>(Math::Vector<2, std::int32_t>(1, 2))),
(Math::Vector<3, std::int32_t>(2, 1, 1)));
CORRADE_COMPARE(swizzle<'z'>(Vector4i(1, 2, 3, 4)),
(Math::Vector<1, std::int32_t>(3)));
CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y', 'z', 'y', 'x'>(Vector4i(1, 2, 3, 4))),
(Math::Vector<7, std::int32_t>(3, 1, 4, 2, 3, 2, 1)));
}
}}}

33
src/Math/Test/SwizzleTest.h

@ -0,0 +1,33 @@
#ifndef Magnum_Math_Test_SwizzleTest_h
#define Magnum_Math_Test_SwizzleTest_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
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 <TestSuite/Tester.h>
namespace Magnum { namespace Math { namespace Test {
class SwizzleTest: public Corrade::TestSuite::Tester {
public:
SwizzleTest();
void components();
void constants();
void sizes();
};
}}}
#endif

30
src/Swizzle.h

@ -15,38 +15,24 @@
GNU Lesser General Public License version 3 for more details.
*/
/** @file
/** @file /Swizzle.h
* @brief Function Magnum::swizzle()
*/
#include "Math/Swizzle.h"
#include "Color.h"
namespace Magnum {
#ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation {
template<std::size_t size, std::size_t position> struct ComponentAtPosition {
static_assert(size > position, "Swizzle parameter out of range of base vector");
template<class T> inline constexpr static T value(const Math::Vector<size, T>& vector) { return vector[position]; }
};
template<std::size_t size, char component> struct Component {};
template<std::size_t size> struct Component<size, 'x'>: public ComponentAtPosition<size, 0> {};
template<std::size_t size> struct Component<size, 'y'>: public ComponentAtPosition<size, 1> {};
template<std::size_t size> struct Component<size, 'z'>: public ComponentAtPosition<size, 2> {};
template<std::size_t size> struct Component<size, 'w'>: public ComponentAtPosition<size, 3> {};
namespace Math { namespace Implementation {
template<std::size_t size> struct Component<size, 'r'>: public ComponentAtPosition<size, 0> {};
template<std::size_t size> struct Component<size, 'g'>: public ComponentAtPosition<size, 1> {};
template<std::size_t size> struct Component<size, 'b'>: public ComponentAtPosition<size, 2> {};
template<std::size_t size> struct Component<size, 'a'>: public ComponentAtPosition<size, 3> {};
template<std::size_t size> struct Component<size, '0'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(0); }
};
template<std::size_t size> struct Component<size, '1'> {
template<class T> inline constexpr static T value(const Math::Vector<size, T>&) { return T(1); }
};
}}
namespace Implementation {
template<std::size_t size, class T> struct TypeForSize {
typedef Math::Vector<size, typename T::Type> Type;
};
@ -76,11 +62,11 @@ unlimited, but must be at least one. If the resulting vector is two, three or
four-component, corresponding Math::Vector2, Math::Vector3, Math::Vector4,
Color3 or Color4 specialization is returned.
@see @ref matrix-vector-component-access, Vector4::xyz(), Color4::rgb(),
Vector4::xy(), Vector3::xy()
@see @ref matrix-vector-component-access, Math::swizzle(), Vector4::xyz(),
Color4::rgb(), Vector4::xy(), Vector3::xy()
*/
template<char ...components, class T> inline constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type swizzle(const T& vector) {
return {Implementation::Component<T::Size, components>::value(vector)...};
return {Math::Implementation::Component<T::Size, components>::value(vector)...};
}
}

17
src/Test/SwizzleTest.cpp

@ -22,30 +22,15 @@ CORRADE_TEST_MAIN(Magnum::Test::SwizzleTest)
namespace Magnum { namespace Test {
SwizzleTest::SwizzleTest() {
addTests(&SwizzleTest::xyzw,
&SwizzleTest::rgba,
&SwizzleTest::constants,
&SwizzleTest::fromSmall,
addTests(&SwizzleTest::rgba,
&SwizzleTest::type,
&SwizzleTest::defaultType);
}
void SwizzleTest::xyzw() {
CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4));
}
void SwizzleTest::rgba() {
CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4));
}
void SwizzleTest::constants() {
CORRADE_COMPARE((swizzle<'1', 'w', '0', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(1, 7, 0, 4));
}
void SwizzleTest::fromSmall() {
CORRADE_COMPARE((swizzle<'g', 'x', 'r'>(Vector2i(1, 2))), Vector3i(2, 1, 1));
}
void SwizzleTest::type() {
Vector4i orig;
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a'>(orig)), Vector2i>::value));

3
src/Test/SwizzleTest.h

@ -23,10 +23,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester {
public:
SwizzleTest();
void xyzw();
void rgba();
void constants();
void fromSmall();
void type();
void defaultType();
};

Loading…
Cancel
Save