From dff1a1ce60607381946e04cdfcaadfe47a7109f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 6 Mar 2023 17:50:46 +0100 Subject: [PATCH] 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. --- src/Magnum/Math/PackingBatch.cpp | 60 ++++++++++++++++++++ src/Magnum/Math/PackingBatch.h | 67 ++++++++++++++++++++++ src/Magnum/Math/Test/PackingBatchTest.cpp | 68 ++++++++++++++--------- 3 files changed, 170 insertions(+), 25 deletions(-) diff --git a/src/Magnum/Math/PackingBatch.cpp b/src/Magnum/Math/PackingBatch.cpp index b75246a68..54ed1eff1 100644 --- a/src/Magnum/Math/PackingBatch.cpp +++ b/src/Magnum/Math/PackingBatch.cpp @@ -26,6 +26,7 @@ #include "PackingBatch.h" #include +#include #include #include "Magnum/Math/Packing.h" @@ -400,6 +401,65 @@ void castInto(const Corrade::Containers::StridedArrayView2D& src, castIntoImplementation(src, dst); } +namespace { + +template inline void copyImplementation(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& 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& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + copyImplementation(src, dst); +} + static_assert(sizeof(HalfMantissaTable) + sizeof(HalfOffsetTable) + sizeof(HalfExponentTable) == 8576, "improper size of half->float conversion tables"); diff --git a/src/Magnum/Math/PackingBatch.h b/src/Magnum/Math/PackingBatch.h index 403c817b4..ea96e1f28 100644 --- a/src/Magnum/Math/PackingBatch.h +++ b/src/Magnum/Math/PackingBatch.h @@ -557,6 +557,73 @@ contiguous. */ MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& 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& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** + * @overload + * @m_since_latest + */ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ /** diff --git a/src/Magnum/Math/Test/PackingBatchTest.cpp b/src/Magnum/Math/Test/PackingBatchTest.cpp index 2efed391a..eed84d288 100644 --- a/src/Magnum/Math/Test/PackingBatchTest.cpp +++ b/src/Magnum/Math/Test/PackingBatchTest.cpp @@ -56,8 +56,7 @@ struct PackingBatchTest: Corrade::TestSuite::Tester { template void castUnsignedInteger(); template void castSignedInteger(); - - void castFloatDouble(); + template void castFloatDouble(); template void assertionsPackUnpack(); void assertionsPackUnpackHalf(); @@ -90,20 +89,29 @@ PackingBatchTest::PackingBatchTest() { &PackingBatchTest::castSignedFloatingPoint, &PackingBatchTest::castSignedFloatingPoint, + &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, + &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, + &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, &PackingBatchTest::castUnsignedInteger, + &PackingBatchTest::castUnsignedInteger, + &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, + &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, + &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, - - &PackingBatchTest::castFloatDouble, + &PackingBatchTest::castSignedInteger, + &PackingBatchTest::castFloatDouble, + &PackingBatchTest::castFloatDouble, + &PackingBatchTest::castFloatDouble, &PackingBatchTest::assertionsPackUnpack, &PackingBatchTest::assertionsPackUnpack, @@ -122,19 +130,29 @@ PackingBatchTest::PackingBatchTest() { &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, - &PackingBatchTest::assertionsCast}); + &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast}); } typedef Math::Constants Constants; @@ -603,38 +621,38 @@ template void PackingBatchTest::castSignedInteger() { Corrade::TestSuite::Compare::Container); } -void PackingBatchTest::castFloatDouble() { +template void PackingBatchTest::castFloatDouble() { struct Data { - Math::Vector2 src; - Math::Vector2 dst; + Math::Vector2 src; + Math::Vector2 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 expectedTargetType[] { - {0.25, -89.5}, - {-119.0, 22.75}, - {13.0, 127.5} + constexpr Math::Vector2 expectedTargetType[] { + {U(0.25), U(-89.5)}, + {U(-119.0), U(22.75)}, + {U(13.0), U(127.5)} }; - constexpr Math::Vector2 expectedOriginalType[] { - {0.25f, -89.5f}, - {-119.0f, 22.75f}, - {13.0f, 127.5f} + constexpr Math::Vector2 expectedOriginalType[] { + {T(0.25), T(-89.5)}, + {T(-119.0), T(22.75)}, + {T(13.0), T(127.5)} }; - Corrade::Containers::StridedArrayView1D> src{data, &data[0].src, 3, sizeof(Data)}; - Corrade::Containers::StridedArrayView1D> dst{data, &data[0].dst, 3, sizeof(Data)}; - castInto(Corrade::Containers::arrayCast<2, Float>(src), - Corrade::Containers::arrayCast<2, Double>(dst)); + Corrade::Containers::StridedArrayView1D> src{data, &data[0].src, 3, sizeof(Data)}; + Corrade::Containers::StridedArrayView1D> 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); }