Browse Source

Removed one swizzle() overload.

It is less efficient because of all that runtime computation and can't
be made to use SIMD operations so why bother with it at all.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
dd8eb6bc02
  1. 6
      doc/matrix-vector.dox
  2. 64
      src/Swizzle.h
  3. 30
      src/Test/SwizzleTest.cpp

6
doc/matrix-vector.dox

@ -134,13 +134,11 @@ xyz.xy() *= 5;
@endcode @endcode
Color3 and Color4 name their components `rgba` instead of `xyzw`. Color3 and Color4 name their components `rgba` instead of `xyzw`.
For more involved operations with components there are two swizzle() functions, For more involved operations with components there is the swizzle() function:
they have the same features, but one is guaranteed to do most of the work at
compile-time, while the second has more convenient syntax:
@code @code
Vector4<int> original(-1, 2, 3, 4); Vector4<int> original(-1, 2, 3, 4);
Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 } Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 }
Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, -1, 2, 3 } Vector<6, int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); // { 4, 1, 0, -1, 2, 3 }
@endcode @endcode
@section matrix-vector-column-major Matrices are column-major and vectors are columns @section matrix-vector-column-major Matrices are column-major and vectors are columns

64
src/Swizzle.h

@ -16,7 +16,7 @@
*/ */
/** @file /** @file
* @brief Functions Magnum::swizzle(const T&), Magnum::swizzle(const T&, const char(&)[]) * @brief Function Magnum::swizzle()
*/ */
#include "Color.h" #include "Color.h"
@ -25,9 +25,6 @@ namespace Magnum {
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
namespace Implementation { namespace Implementation {
using Math::Implementation::Sequence;
using Math::Implementation::GenerateSequence;
template<std::size_t size, std::size_t position> struct ComponentAtPosition { template<std::size_t size, std::size_t position> struct ComponentAtPosition {
static_assert(size > position, "Swizzle parameter out of range of base vector"); static_assert(size > position, "Swizzle parameter out of range of base vector");
@ -60,28 +57,6 @@ namespace Implementation {
template<class T> struct TypeForSize<3, Color4<T>> { typedef Color3<T> Type; }; template<class T> struct TypeForSize<3, Color4<T>> { typedef Color3<T> Type; };
template<class T> struct TypeForSize<4, Color3<T>> { typedef Color4<T> Type; }; template<class T> struct TypeForSize<4, Color3<T>> { typedef Color4<T> Type; };
template<class T> struct TypeForSize<4, Color4<T>> { typedef Color4<T> Type; }; template<class T> struct TypeForSize<4, Color4<T>> { typedef Color4<T> Type; };
template<std::size_t size, class T> inline constexpr T componentAtPosition(const Math::Vector<size, T>& vector, std::size_t position) {
return size > position ? vector[position] : throw;
}
template<std::size_t size, class T> inline constexpr T component(const Math::Vector<size, T>& vector, char component) {
return component == 'x' ? componentAtPosition(vector, 0) :
component == 'y' ? componentAtPosition(vector, 1) :
component == 'z' ? componentAtPosition(vector, 2) :
component == 'w' ? componentAtPosition(vector, 3) :
component == 'r' ? componentAtPosition(vector, 0) :
component == 'g' ? componentAtPosition(vector, 1) :
component == 'b' ? componentAtPosition(vector, 2) :
component == 'a' ? componentAtPosition(vector, 3) :
component == '0' ? T(0) :
component == '1' ? T(1) :
throw;
}
template<std::size_t size, class T, std::size_t ...sequence> inline constexpr Math::Vector<sizeof...(sequence), T> swizzleFrom(Sequence<sequence...>, const Math::Vector<size, T>& vector, const char(&components)[sizeof...(sequence)+1]) {
return {component<size>(vector, components[sequence])...};
}
} }
#endif #endif
@ -98,13 +73,8 @@ auto vec = swizzle<'a', '1', '0', 'r', 'g', 'b'>(original);
You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing
components or letters `0` and `1` for zero and one. Count of elements is components or letters `0` and `1` for zero and one. Count of elements is
unlimited, but must be at least one. If the resulting vector is two, three or unlimited, but must be at least one. If the resulting vector is two, three or
four-component, corresponding Vector2, Vector3, Vector4, Color3 or Color4 four-component, corresponding Math::Vector2, Math::Vector3, Math::Vector4,
specialization is returned. Color3 or Color4 specialization is returned.
@attention This function is less convenient to write than
swizzle(const T&, const char(&)[newSize]), but the evaluation of
the swizzling operation is guaranteed to be always done at compile time
instead of at runtime.
@see @ref matrix-vector-component-access, Vector4::xyz(), Color4::rgb(), @see @ref matrix-vector-component-access, Vector4::xyz(), Color4::rgb(),
Vector4::xy(), Vector3::xy() Vector4::xy(), Vector3::xy()
@ -113,34 +83,6 @@ template<char ...components, class T> inline constexpr typename Implementation::
return {Implementation::Component<T::Size, components>::value(vector)...}; return {Implementation::Component<T::Size, components>::value(vector)...};
} }
/**
@brief Swizzle Vector components
Creates new vector from given components. Example:
@code
Vector4i original(-1, 2, 3, 4);
auto vec = swizzle(original, "a10rgb");
// vec == { 4, 1, 0, -1, 2, 3 }
@endcode
You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing
components or letters `0` and `1` for zero and one. Count of elements is
unlimited, but must be at least one. If the resulting vector is two, three or
four-component, corresponding Vector2, Vector3 or Vector4 specialization is
returned.
@attention This function is more convenient to write than
swizzle(const T&), but unless the result is marked with
`constexpr`, the evaluation of the swizzling operation probably won't be
evaluated at compile time, but at runtime.
@see @ref matrix-vector-component-access, Vector4::xyz(), Color4::rgb(),
Vector4::xy(), Vector3::xy()
*/
template<class T, std::size_t newSize> inline constexpr typename Implementation::TypeForSize<newSize-1, T>::Type swizzle(const T& vector, const char(&components)[newSize]) {
return Implementation::swizzleFrom(typename Implementation::GenerateSequence<newSize-1>::Type(), vector, components);
}
} }
#endif #endif

30
src/Test/SwizzleTest.cpp

@ -31,61 +31,39 @@ SwizzleTest::SwizzleTest() {
} }
void SwizzleTest::xyzw() { void SwizzleTest::xyzw() {
Vector4i orig(2, 4, 5, 7); CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4));
Vector4i swizzled(5, 2, 7, 4);
CORRADE_COMPARE(swizzle(orig, "zxwy"), swizzled);
CORRADE_COMPARE((swizzle<'z', 'x', 'w', 'y'>(orig)), swizzled);
} }
void SwizzleTest::rgba() { void SwizzleTest::rgba() {
Vector4i orig(2, 4, 5, 7); CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(5, 2, 7, 4));
Vector4i swizzled(5, 2, 7, 4);
CORRADE_COMPARE(swizzle(orig, "brag"), swizzled);
CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g'>(orig)), swizzled);
} }
void SwizzleTest::constants() { void SwizzleTest::constants() {
Vector4i orig(2, 4, 5, 7); CORRADE_COMPARE((swizzle<'1', 'w', '0', 'g'>(Vector4i(2, 4, 5, 7))), Vector4i(1, 7, 0, 4));
Vector4i swizzled(1, 7, 0, 4);
CORRADE_COMPARE(swizzle(orig, "1w0g"), swizzled);
CORRADE_COMPARE((swizzle<'1', 'w', '0', 'g'>(orig)), swizzled);
} }
void SwizzleTest::fromSmall() { void SwizzleTest::fromSmall() {
/* Force compile-time evaluation for both */ CORRADE_COMPARE((swizzle<'g', 'x', 'r'>(Vector2i(1, 2))), Vector3i(2, 1, 1));
constexpr Vector2i orig(1, 2);
constexpr Vector3i swizzled(swizzle(orig, "gxr"));
CORRADE_VERIFY((std::integral_constant<bool, swizzled.x() == 2>::value));
CORRADE_COMPARE((swizzle<'g', 'x', 'r'>(orig)), Vector3i(2, 1, 1));
} }
void SwizzleTest::type() { void SwizzleTest::type() {
Vector4i orig; Vector4i orig;
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a'>(orig)), Vector2i>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a'>(orig)), Vector2i>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(orig, "ya")), Vector2i>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'a'>(orig)), Vector3i>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'a'>(orig)), Vector3i>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(orig, "yza")), Vector3i>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a', 'y', 'x'>(orig)), Vector4i>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a', 'y', 'x'>(orig)), Vector4i>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(orig, "yayx")), Vector4i>::value));
Color3<float> origColor3; Color3<float> origColor3;
Color4<double> origColor4; Color4<double> origColor4;
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'r'>(origColor3)), Color3<>>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'r'>(origColor3)), Color3<>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'a'>(origColor4)), Color3<double>>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'a'>(origColor4)), Color3<double>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(origColor3, "yzr")), Color3<>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(origColor4, "yza")), Color3<double>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'y', 'x'>(origColor3)), Color4<>>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'z', 'y', 'x'>(origColor3)), Color4<>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a', 'y', 'x'>(origColor4)), Color4<double>>::value)); CORRADE_VERIFY((std::is_same<decltype(swizzle<'y', 'a', 'y', 'x'>(origColor4)), Color4<double>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(origColor3, "yzyx")), Color4<>>::value));
CORRADE_VERIFY((std::is_same<decltype(swizzle(origColor4, "yayx")), Color4<double>>::value));
} }
void SwizzleTest::defaultType() { void SwizzleTest::defaultType() {
Vector4i orig(1, 2, 3, 4); Vector4i orig(1, 2, 3, 4);
CORRADE_COMPARE(swizzle<'b'>(orig), (Math::Vector<1, std::int32_t>(3))); CORRADE_COMPARE(swizzle<'b'>(orig), (Math::Vector<1, std::int32_t>(3)));
CORRADE_COMPARE(swizzle(orig, "b"), (Math::Vector<1, std::int32_t>(3)));
CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig)), (Math::Vector<7, std::int32_t>(3, 1, 4, 2, 3, 2, 1))); CORRADE_COMPARE((swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig)), (Math::Vector<7, std::int32_t>(3, 1, 4, 2, 3, 2, 1)));
CORRADE_COMPARE(swizzle(orig, "bragzyx"), (Math::Vector<7, std::int32_t>(3, 1, 4, 2, 3, 2, 1)));
} }
}} }}

Loading…
Cancel
Save