Browse Source

Math: add integer-to-integer castInto() variants also.

Currently one of the types is always 32-bit and preserving signedness,
because that's what I need right now. Other variants might get added
later.
pull/430/head
Vladimír Vondruš 6 years ago
parent
commit
f3566f637f
  1. 10
      doc/changelog.dox
  2. 32
      src/Magnum/Math/PackingBatch.cpp
  3. 59
      src/Magnum/Math/PackingBatch.h
  4. 145
      src/Magnum/Math/Test/PackingBatchTest.cpp

10
doc/changelog.dox

@ -110,6 +110,11 @@ See also:
@subsubsection changelog-latest-new-math Math library @subsubsection changelog-latest-new-math Math library
- New @ref Magnum/Math/PackingBatch.h header with batch
@ref Math::packInto(), @ref Math::unpackInto(),
@ref Math::packHalfInto(), @ref Math::unpackHalfInto() and
@ref Math::castInto() functions for optimized (un)packing and casting of
large amounts of data (see also [mosra/magnum#275](https://github.com/mosra/magnum/pull/275))
- Added @ref Math::Quaternion::toEuler() and documented how to convert Euler - Added @ref Math::Quaternion::toEuler() and documented how to convert Euler
angles to a quaternion (see [mosra/magnum#397](https://github.com/mosra/magnum/pull/397)) angles to a quaternion (see [mosra/magnum#397](https://github.com/mosra/magnum/pull/397))
- Added @ref Math::DualComplex::transformVector(), - Added @ref Math::DualComplex::transformVector(),
@ -262,11 +267,6 @@ See also:
- Functions in @ref Magnum/Math/FunctionsBatch.h now accept any type that's - Functions in @ref Magnum/Math/FunctionsBatch.h now accept any type that's
convertible to a @ref Corrade::Containers::StridedArrayView without having convertible to a @ref Corrade::Containers::StridedArrayView without having
to add explicit casts or template parameters to add explicit casts or template parameters
- New @ref Magnum/Math/PackingBatch.h header with batch
@ref Math::packInto(), @ref Math::unpackInto(),
@ref Math::packHalfInto(), @ref Math::unpackHalfInto() and
@ref Math::castInto() functions for optimized (un)packing of large amounts
of data (see also [mosra/magnum#275](https://github.com/mosra/magnum/pull/275))
- @ref Math::slerp(const Quaternion<T>&, const Quaternion<T>&, T) and - @ref Math::slerp(const Quaternion<T>&, const Quaternion<T>&, T) and
@ref Math::slerpShortestPath(const Quaternion<T>&, const Quaternion<T>&, T) @ref Math::slerpShortestPath(const Quaternion<T>&, const Quaternion<T>&, T)
now fall back to linear interpolation when the quaternions are close to now fall back to linear interpolation when the quaternions are close to

32
src/Magnum/Math/PackingBatch.cpp

@ -240,6 +240,38 @@ void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, c
castIntoImplementation(src, dst); castIntoImplementation(src, dst);
} }
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst) {
castIntoImplementation(src, dst);
}
static_assert(sizeof(HalfMantissaTable) + sizeof(HalfOffsetTable) + sizeof(HalfExponentTable) == 8576, static_assert(sizeof(HalfMantissaTable) + sizeof(HalfOffsetTable) + sizeof(HalfExponentTable) == 8576,
"improper size of half->float conversion tables"); "improper size of half->float conversion tables");

59
src/Magnum/Math/PackingBatch.h

@ -265,6 +265,65 @@ MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const
*/ */
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst); MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst);
/**
@brief Cast integer values into a differently sized type
@param[in] src Source values
@param[out] dst Destination values
@m_since_latest
Second dimension is meant to contain vector/matrix components, or have a size
of 1 for scalars. Expects that @p src and @p dst have the same size and that
the second dimension in both is contiguous.
@attention Values that don't fit into the resulting type will have undefined
values.
@see @ref Corrade::Containers::StridedArrayView::isContiguous()
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst);
/*@}*/ /*@}*/
}} }}

145
src/Magnum/Math/Test/PackingBatchTest.cpp

@ -28,6 +28,7 @@
#include <Corrade/TestSuite/Tester.h> #include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h> #include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Packing.h" #include "Magnum/Math/Packing.h"
@ -51,12 +52,15 @@ struct PackingBatchTest: Corrade::TestSuite::Tester {
void unpackHalf(); void unpackHalf();
void packHalf(); void packHalf();
template<class T> void castUnsigned(); template<class T> void castUnsignedFloat();
template<class T> void castSigned(); template<class T> void castSignedFloat();
template<class T> void castUnsignedInteger();
template<class T> void castSignedInteger();
template<class T> void assertionsPackUnpack(); template<class T> void assertionsPackUnpack();
void assertionsPackUnpackHalf(); void assertionsPackUnpackHalf();
template<class T> void assertionsCast(); template<class U, class T> void assertionsCast();
}; };
PackingBatchTest::PackingBatchTest() { PackingBatchTest::PackingBatchTest() {
@ -72,24 +76,33 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::unpackHalf, &PackingBatchTest::unpackHalf,
&PackingBatchTest::packHalf, &PackingBatchTest::packHalf,
&PackingBatchTest::castUnsigned<UnsignedByte>, &PackingBatchTest::castUnsignedFloat<UnsignedByte>,
&PackingBatchTest::castUnsigned<UnsignedShort>, &PackingBatchTest::castUnsignedFloat<UnsignedShort>,
&PackingBatchTest::castUnsigned<UnsignedInt>, &PackingBatchTest::castUnsignedFloat<UnsignedInt>,
&PackingBatchTest::castSigned<Byte>, &PackingBatchTest::castSignedFloat<Byte>,
&PackingBatchTest::castSigned<Short>, &PackingBatchTest::castSignedFloat<Short>,
&PackingBatchTest::castSigned<Int>, &PackingBatchTest::castSignedFloat<Int>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte>,
&PackingBatchTest::castUnsignedInteger<UnsignedShort>,
&PackingBatchTest::castSignedInteger<Byte>,
&PackingBatchTest::castSignedInteger<Short>,
&PackingBatchTest::assertionsPackUnpack<UnsignedByte>, &PackingBatchTest::assertionsPackUnpack<UnsignedByte>,
&PackingBatchTest::assertionsPackUnpack<Byte>, &PackingBatchTest::assertionsPackUnpack<Byte>,
&PackingBatchTest::assertionsPackUnpack<UnsignedShort>, &PackingBatchTest::assertionsPackUnpack<UnsignedShort>,
&PackingBatchTest::assertionsPackUnpack<Short>, &PackingBatchTest::assertionsPackUnpack<Short>,
&PackingBatchTest::assertionsPackUnpackHalf, &PackingBatchTest::assertionsPackUnpackHalf,
&PackingBatchTest::assertionsCast<UnsignedByte>, &PackingBatchTest::assertionsCast<Float, UnsignedByte>,
&PackingBatchTest::assertionsCast<Byte>, &PackingBatchTest::assertionsCast<Float, Byte>,
&PackingBatchTest::assertionsCast<UnsignedShort>, &PackingBatchTest::assertionsCast<Float, UnsignedShort>,
&PackingBatchTest::assertionsCast<Short>, &PackingBatchTest::assertionsCast<Float, Short>,
&PackingBatchTest::assertionsCast<UnsignedInt>, &PackingBatchTest::assertionsCast<Float, UnsignedInt>,
&PackingBatchTest::assertionsCast<Int>}); &PackingBatchTest::assertionsCast<Float, Int>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedShort>,
&PackingBatchTest::assertionsCast<Int, Byte>,
&PackingBatchTest::assertionsCast<Int, Short>});
} }
typedef Math::Constants<Float> Constants; typedef Math::Constants<Float> Constants;
@ -98,6 +111,8 @@ typedef Math::Vector2<UnsignedShort> Vector2us;
typedef Math::Vector2<Byte> Vector2b; typedef Math::Vector2<Byte> Vector2b;
typedef Math::Vector2<Short> Vector2s; typedef Math::Vector2<Short> Vector2s;
typedef Math::Vector2<Float> Vector2; typedef Math::Vector2<Float> Vector2;
typedef Math::Vector2<UnsignedInt> Vector2ui;
typedef Math::Vector2<Int> Vector2i;
typedef Math::Vector3<Float> Vector3; typedef Math::Vector3<Float> Vector3;
typedef Math::Vector4<Float> Vector4; typedef Math::Vector4<Float> Vector4;
@ -399,7 +414,7 @@ void PackingBatchTest::packHalf() {
CORRADE_COMPARE(Math::packHalf(data[i].src), data[i].dst); CORRADE_COMPARE(Math::packHalf(data[i].src), data[i].dst);
} }
template<class T> void PackingBatchTest::castUnsigned() { template<class T> void PackingBatchTest::castUnsignedFloat() {
setTestCaseTemplateName(TypeTraits<T>::name()); setTestCaseTemplateName(TypeTraits<T>::name());
struct Data { struct Data {
@ -439,7 +454,7 @@ template<class T> void PackingBatchTest::castUnsigned() {
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
} }
template<class T> void PackingBatchTest::castSigned() { template<class T> void PackingBatchTest::castSignedFloat() {
setTestCaseTemplateName(TypeTraits<T>::name()); setTestCaseTemplateName(TypeTraits<T>::name());
struct Data { struct Data {
@ -479,6 +494,86 @@ template<class T> void PackingBatchTest::castSigned() {
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
} }
template<class T> void PackingBatchTest::castUnsignedInteger() {
setTestCaseTemplateName(TypeTraits<T>::name());
struct Data {
Math::Vector2<T> src;
Vector2ui dst;
} data[]{
{{0, 89}, {}},
{{149, 22}, {}},
{{13, 255}, {}}
};
/* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type
const Vector2 [3] with a compound literal), wtf */
const Vector2ui expectedTargetType[] {
{0, 89},
{149, 22},
{13, 255}
};
constexpr Math::Vector2<T> expectedOriginalType[] {
{0, 89},
{149, 22},
{13, 255}
};
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Vector2ui> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, T>(src),
Corrade::Containers::arrayCast<2, UnsignedInt>(dst));
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedTargetType),
Corrade::TestSuite::Compare::Container);
/* Test the other way around as well */
castInto(Corrade::Containers::arrayCast<2, UnsignedInt>(dst),
Corrade::Containers::arrayCast<2, T>(src));
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedOriginalType),
Corrade::TestSuite::Compare::Container);
}
template<class T> void PackingBatchTest::castSignedInteger() {
setTestCaseTemplateName(TypeTraits<T>::name());
struct Data {
Math::Vector2<T> src;
Vector2i dst;
} data[]{
{{0, -89}, {}},
{{-119, 22}, {}},
{{13, 127}, {}}
};
/* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type
const Vector2 [3] with a compound literal), wtf */
const Vector2i expectedTargetType[] {
{0, -89},
{-119, 22},
{13, 127}
};
constexpr Math::Vector2<T> expectedOriginalType[] {
{0, -89},
{-119, 22},
{13, 127}
};
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Vector2i> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, T>(src),
Corrade::Containers::arrayCast<2, Int>(dst));
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedTargetType),
Corrade::TestSuite::Compare::Container);
/* Test the other way around as well */
castInto(Corrade::Containers::arrayCast<2, Int>(dst),
Corrade::Containers::arrayCast<2, T>(src));
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedOriginalType),
Corrade::TestSuite::Compare::Container);
}
template<class T> void PackingBatchTest::assertionsPackUnpack() { template<class T> void PackingBatchTest::assertionsPackUnpack() {
Math::Vector2<T> data[2]{}; Math::Vector2<T> data[2]{};
Vector2 resultWrongCount[1]{}; Vector2 resultWrongCount[1]{};
@ -543,19 +638,21 @@ void PackingBatchTest::assertionsPackUnpackHalf() {
"Math::packHalfInto(): second view dimension is not contiguous\n"); "Math::packHalfInto(): second view dimension is not contiguous\n");
} }
template<class T> void PackingBatchTest::assertionsCast() { template<class U, class T> void PackingBatchTest::assertionsCast() {
setTestCaseTemplateName(Corrade::Utility::formatString("{}, {}", TypeTraits<U>::name(), TypeTraits<T>::name()));
Math::Vector2<T> data[2]{}; Math::Vector2<T> data[2]{};
Vector2 resultWrongCount[1]{}; Math::Vector2<U> resultWrongCount[1]{};
Vector3 resultWrongVectorSize[2]{}; Math::Vector3<U> resultWrongVectorSize[2]{};
Vector4 resultNonContiguous[2]{}; Math::Vector4<U> resultNonContiguous[2]{};
auto src = Corrade::Containers::arrayCast<2, T>( auto src = Corrade::Containers::arrayCast<2, T>(
Corrade::Containers::arrayView(data)); Corrade::Containers::arrayView(data));
auto dstWrongCount = Corrade::Containers::arrayCast<2, Float>( auto dstWrongCount = Corrade::Containers::arrayCast<2, U>(
Corrade::Containers::arrayView(resultWrongCount)); Corrade::Containers::arrayView(resultWrongCount));
auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, Float>( auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, U>(
Corrade::Containers::arrayView(resultWrongVectorSize)); Corrade::Containers::arrayView(resultWrongVectorSize));
auto dstNotContiguous = Corrade::Containers::arrayCast<2, Float>( auto dstNotContiguous = Corrade::Containers::arrayCast<2, U>(
Corrade::Containers::arrayView(resultNonContiguous)).every({1, 2}); Corrade::Containers::arrayView(resultNonContiguous)).every({1, 2});
std::ostringstream out; std::ostringstream out;

Loading…
Cancel
Save