Browse Source

Math: add also castInto(T[], T[]) overloads.

For generic code, which would otherwise have to invent some SFINAE
"use castInto() if the types are different and Utility::copy()
otherwise" nastiness in every such case, and that's just annoying.
pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
dff1a1ce60
  1. 60
      src/Magnum/Math/PackingBatch.cpp
  2. 67
      src/Magnum/Math/PackingBatch.h
  3. 68
      src/Magnum/Math/Test/PackingBatchTest.cpp

60
src/Magnum/Math/PackingBatch.cpp

@ -26,6 +26,7 @@
#include "PackingBatch.h"
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Utility/Algorithms.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/Math/Packing.h"
@ -400,6 +401,65 @@ void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src,
castIntoImplementation(src, dst);
}
namespace {
template<class T> inline void copyImplementation(const Corrade::Containers::StridedArrayView2D<const T>& src, const Corrade::Containers::StridedArrayView2D<T>& dst) {
/* Utility::copy() has its own assertions, but those are debug-only for
perf reasons and don't require the second dimension to be contiguous.
Here the use case is different and the behavior should be consistent
with other castInto() overloads to avoid surprises. */
CORRADE_ASSERT(src.size() == dst.size(),
"Math::castInto(): wrong destination size, got" << dst.size() << "but expected" << src.size(), );
CORRADE_ASSERT(src.template isContiguous<1>(),
"Math::castInto(): second source view dimension is not contiguous", );
CORRADE_ASSERT(dst.template isContiguous<1>(),
"Math::castInto(): second destination view dimension is not contiguous", );
Corrade::Utility::copy(src, dst);
}
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedLong>& src, const Corrade::Containers::StridedArrayView2D<UnsignedLong>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Long>& src, const Corrade::Containers::StridedArrayView2D<Long>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) {
copyImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
copyImplementation(src, dst);
}
static_assert(sizeof(HalfMantissaTable) + sizeof(HalfOffsetTable) + sizeof(HalfExponentTable) == 8576,
"improper size of half->float conversion tables");

67
src/Magnum/Math/PackingBatch.h

@ -557,6 +557,73 @@ contiguous.
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst);
/**
@brief Copy values
@param[in] src Source values
@param[out] dst Destination values
@m_since_latest
Provided for convenience when writing generic code, delegates to @relativeref{Corrade,Utility::copy()}. Expects that @p src and @p dst have the
same size, for consistency with other @ref castInto() expects also that the
second dimension in both is contiguous even though it's not required by
@relativeref{Corrade,Utility::copy()}.
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& 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<UnsignedInt>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedLong>& src, const Corrade::Containers::StridedArrayView2D<UnsignedLong>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Long>& src, const Corrade::Containers::StridedArrayView2D<Long>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/* Since 1.8.17, the original short-hand group closing doesn't work anymore.
FFS. */
/**

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

@ -56,8 +56,7 @@ struct PackingBatchTest: Corrade::TestSuite::Tester {
template<class T, class U> void castUnsignedInteger();
template<class T, class U> void castSignedInteger();
void castFloatDouble();
template<class T, class U> void castFloatDouble();
template<class T> void assertionsPackUnpack();
void assertionsPackUnpackHalf();
@ -90,20 +89,29 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::castSignedFloatingPoint<Double, Short>,
&PackingBatchTest::castSignedFloatingPoint<Double, Int>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedByte>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedShort>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedInt>,
&PackingBatchTest::castUnsignedInteger<UnsignedShort, UnsignedShort>,
&PackingBatchTest::castUnsignedInteger<UnsignedShort, UnsignedInt>,
&PackingBatchTest::castUnsignedInteger<UnsignedInt, UnsignedInt>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedLong>,
&PackingBatchTest::castUnsignedInteger<UnsignedShort, UnsignedLong>,
&PackingBatchTest::castUnsignedInteger<UnsignedInt, UnsignedLong>,
&PackingBatchTest::castUnsignedInteger<UnsignedLong, UnsignedLong>,
&PackingBatchTest::castSignedInteger<Byte, Byte>,
&PackingBatchTest::castSignedInteger<Byte, Short>,
&PackingBatchTest::castSignedInteger<Byte, Int>,
&PackingBatchTest::castSignedInteger<Short, Short>,
&PackingBatchTest::castSignedInteger<Short, Int>,
&PackingBatchTest::castSignedInteger<Int, Int>,
&PackingBatchTest::castSignedInteger<Byte, Long>,
&PackingBatchTest::castSignedInteger<Short, Long>,
&PackingBatchTest::castSignedInteger<Int, Long>,
&PackingBatchTest::castFloatDouble,
&PackingBatchTest::castSignedInteger<Long, Long>,
&PackingBatchTest::castFloatDouble<Float, Double>,
&PackingBatchTest::castFloatDouble<Float, Float>,
&PackingBatchTest::castFloatDouble<Double, Double>,
&PackingBatchTest::assertionsPackUnpack<UnsignedByte>,
&PackingBatchTest::assertionsPackUnpack<Byte>,
@ -122,19 +130,29 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::assertionsCast<Double, Short>,
&PackingBatchTest::assertionsCast<Double, UnsignedInt>,
&PackingBatchTest::assertionsCast<Double, Int>,
&PackingBatchTest::assertionsCast<UnsignedByte, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedShort, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedShort, UnsignedShort>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedShort>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedInt>,
&PackingBatchTest::assertionsCast<UnsignedLong, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedLong, UnsignedShort>,
&PackingBatchTest::assertionsCast<UnsignedLong, UnsignedInt>,
&PackingBatchTest::assertionsCast<UnsignedLong, UnsignedLong>,
&PackingBatchTest::assertionsCast<Byte, Byte>,
&PackingBatchTest::assertionsCast<Short, Byte>,
&PackingBatchTest::assertionsCast<Short, Short>,
&PackingBatchTest::assertionsCast<Int, Byte>,
&PackingBatchTest::assertionsCast<Int, Short>,
&PackingBatchTest::assertionsCast<Int, Int>,
&PackingBatchTest::assertionsCast<Long, Byte>,
&PackingBatchTest::assertionsCast<Long, Short>,
&PackingBatchTest::assertionsCast<Long, Int>,
&PackingBatchTest::assertionsCast<Double, Float>});
&PackingBatchTest::assertionsCast<Long, Long>,
&PackingBatchTest::assertionsCast<Float, Float>,
&PackingBatchTest::assertionsCast<Double, Float>,
&PackingBatchTest::assertionsCast<Double, Double>});
}
typedef Math::Constants<Float> Constants;
@ -603,38 +621,38 @@ template<class T, class U> void PackingBatchTest::castSignedInteger() {
Corrade::TestSuite::Compare::Container);
}
void PackingBatchTest::castFloatDouble() {
template<class T, class U> void PackingBatchTest::castFloatDouble() {
struct Data {
Math::Vector2<Float> src;
Math::Vector2<Double> dst;
Math::Vector2<T> src;
Math::Vector2<U> dst;
} data[]{
{{0.25f, -89.5f}, {}},
{{-119.0f, 22.75f}, {}},
{{13.0f, 127.5f}, {}}
{{T(0.25), T(-89.5)}, {}},
{{T(-119.0), T(22.75)}, {}},
{{T(13.0), T(127.5)}, {}}
};
constexpr Math::Vector2<Double> expectedTargetType[] {
{0.25, -89.5},
{-119.0, 22.75},
{13.0, 127.5}
constexpr Math::Vector2<U> expectedTargetType[] {
{U(0.25), U(-89.5)},
{U(-119.0), U(22.75)},
{U(13.0), U(127.5)}
};
constexpr Math::Vector2<Float> expectedOriginalType[] {
{0.25f, -89.5f},
{-119.0f, 22.75f},
{13.0f, 127.5f}
constexpr Math::Vector2<T> expectedOriginalType[] {
{T(0.25), T(-89.5)},
{T(-119.0), T(22.75)},
{T(13.0), T(127.5)}
};
Corrade::Containers::StridedArrayView1D<Math::Vector2<Float>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Math::Vector2<Double>> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, Float>(src),
Corrade::Containers::arrayCast<2, Double>(dst));
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Math::Vector2<U>> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, T>(src),
Corrade::Containers::arrayCast<2, U>(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, Double>(dst),
Corrade::Containers::arrayCast<2, Float>(src));
castInto(Corrade::Containers::arrayCast<2, U>(dst),
Corrade::Containers::arrayCast<2, T>(src));
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedOriginalType),
Corrade::TestSuite::Compare::Container);
}

Loading…
Cancel
Save