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
- 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
angles to a quaternion (see [mosra/magnum#397](https://github.com/mosra/magnum/pull/397))
- Added @ref Math::DualComplex::transformVector(),
@ -262,11 +267,6 @@ See also:
- Functions in @ref Magnum/Math/FunctionsBatch.h now accept any type that's
convertible to a @ref Corrade::Containers::StridedArrayView without having
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::slerpShortestPath(const Quaternion<T>&, const Quaternion<T>&, T)
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);
}
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,
"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);
/**
@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/Compare/Container.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Packing.h"
@ -51,12 +52,15 @@ struct PackingBatchTest: Corrade::TestSuite::Tester {
void unpackHalf();
void packHalf();
template<class T> void castUnsigned();
template<class T> void castSigned();
template<class T> void castUnsignedFloat();
template<class T> void castSignedFloat();
template<class T> void castUnsignedInteger();
template<class T> void castSignedInteger();
template<class T> void assertionsPackUnpack();
void assertionsPackUnpackHalf();
template<class T> void assertionsCast();
template<class U, class T> void assertionsCast();
};
PackingBatchTest::PackingBatchTest() {
@ -72,24 +76,33 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::unpackHalf,
&PackingBatchTest::packHalf,
&PackingBatchTest::castUnsigned<UnsignedByte>,
&PackingBatchTest::castUnsigned<UnsignedShort>,
&PackingBatchTest::castUnsigned<UnsignedInt>,
&PackingBatchTest::castSigned<Byte>,
&PackingBatchTest::castSigned<Short>,
&PackingBatchTest::castSigned<Int>,
&PackingBatchTest::castUnsignedFloat<UnsignedByte>,
&PackingBatchTest::castUnsignedFloat<UnsignedShort>,
&PackingBatchTest::castUnsignedFloat<UnsignedInt>,
&PackingBatchTest::castSignedFloat<Byte>,
&PackingBatchTest::castSignedFloat<Short>,
&PackingBatchTest::castSignedFloat<Int>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte>,
&PackingBatchTest::castUnsignedInteger<UnsignedShort>,
&PackingBatchTest::castSignedInteger<Byte>,
&PackingBatchTest::castSignedInteger<Short>,
&PackingBatchTest::assertionsPackUnpack<UnsignedByte>,
&PackingBatchTest::assertionsPackUnpack<Byte>,
&PackingBatchTest::assertionsPackUnpack<UnsignedShort>,
&PackingBatchTest::assertionsPackUnpack<Short>,
&PackingBatchTest::assertionsPackUnpackHalf,
&PackingBatchTest::assertionsCast<UnsignedByte>,
&PackingBatchTest::assertionsCast<Byte>,
&PackingBatchTest::assertionsCast<UnsignedShort>,
&PackingBatchTest::assertionsCast<Short>,
&PackingBatchTest::assertionsCast<UnsignedInt>,
&PackingBatchTest::assertionsCast<Int>});
&PackingBatchTest::assertionsCast<Float, UnsignedByte>,
&PackingBatchTest::assertionsCast<Float, Byte>,
&PackingBatchTest::assertionsCast<Float, UnsignedShort>,
&PackingBatchTest::assertionsCast<Float, Short>,
&PackingBatchTest::assertionsCast<Float, UnsignedInt>,
&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;
@ -98,6 +111,8 @@ typedef Math::Vector2<UnsignedShort> Vector2us;
typedef Math::Vector2<Byte> Vector2b;
typedef Math::Vector2<Short> Vector2s;
typedef Math::Vector2<Float> Vector2;
typedef Math::Vector2<UnsignedInt> Vector2ui;
typedef Math::Vector2<Int> Vector2i;
typedef Math::Vector3<Float> Vector3;
typedef Math::Vector4<Float> Vector4;
@ -399,7 +414,7 @@ void PackingBatchTest::packHalf() {
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());
struct Data {
@ -439,7 +454,7 @@ template<class T> void PackingBatchTest::castUnsigned() {
Corrade::TestSuite::Compare::Container);
}
template<class T> void PackingBatchTest::castSigned() {
template<class T> void PackingBatchTest::castSignedFloat() {
setTestCaseTemplateName(TypeTraits<T>::name());
struct Data {
@ -479,6 +494,86 @@ template<class T> void PackingBatchTest::castSigned() {
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() {
Math::Vector2<T> data[2]{};
Vector2 resultWrongCount[1]{};
@ -543,19 +638,21 @@ void PackingBatchTest::assertionsPackUnpackHalf() {
"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]{};
Vector2 resultWrongCount[1]{};
Vector3 resultWrongVectorSize[2]{};
Vector4 resultNonContiguous[2]{};
Math::Vector2<U> resultWrongCount[1]{};
Math::Vector3<U> resultWrongVectorSize[2]{};
Math::Vector4<U> resultNonContiguous[2]{};
auto src = Corrade::Containers::arrayCast<2, T>(
Corrade::Containers::arrayView(data));
auto dstWrongCount = Corrade::Containers::arrayCast<2, Float>(
auto dstWrongCount = Corrade::Containers::arrayCast<2, U>(
Corrade::Containers::arrayView(resultWrongCount));
auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, Float>(
auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, U>(
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});
std::ostringstream out;

Loading…
Cancel
Save