Browse Source

Math: add castInto() variants for Double<->integer.

Because yes of course dealing with a JSON just isn't possible
without having to make decisions between insufficiently imprecise
integers and unnecessarly overprecise doubles.
sceneconverter
Vladimír Vondruš 4 years ago
parent
commit
e0909fedfe
  1. 4
      doc/changelog.dox
  2. 48
      src/Magnum/Math/PackingBatch.cpp
  3. 100
      src/Magnum/Math/PackingBatch.h
  4. 96
      src/Magnum/Math/Test/PackingBatchTest.cpp

4
doc/changelog.dox

@ -379,8 +379,8 @@ See also:
- Added @ref Math::castInto() overloads for casting between @ref UnsignedByte - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte
and @ref UnsignedShort or @ref Byte and @ref Short, from and to and @ref UnsignedShort or @ref Byte and @ref Short, from and to
@ref UnsignedLong / @ref Long, and for casting between @ref Float and @ref UnsignedLong / @ref Long, between integral types and @ref Double and
@ref Double for casting between @ref Float and @ref Double
- @ref Math::RectangularMatrix is now explicitly convertible from matrices of - @ref Math::RectangularMatrix is now explicitly convertible from matrices of
different sizes, with a possibility to specify whether to fill the diagonal different sizes, with a possibility to specify whether to fill the diagonal
or leave it as zeros. This was originally available only on (square) or leave it as zeros. This was originally available only on (square)

48
src/Magnum/Math/PackingBatch.cpp

@ -216,6 +216,30 @@ void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, con
castIntoImplementation(src, dst); castIntoImplementation(src, dst);
} }
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) { void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) {
castIntoImplementation(src, dst); castIntoImplementation(src, dst);
} }
@ -240,6 +264,30 @@ void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, c
castIntoImplementation(src, dst); castIntoImplementation(src, dst);
} }
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst) {
castIntoImplementation(src, dst);
}
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) { void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) {
castIntoImplementation(src, dst); castIntoImplementation(src, dst);
} }

100
src/Magnum/Math/PackingBatch.h

@ -215,6 +215,56 @@ MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const
*/ */
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst);
/**
@brief Cast integer values into a 64-bit floating-point representation
@param[in] src Source integral values
@param[out] dst Destination float values
@m_since_latest
Unlike @ref packInto(), this function performs only an equivalent of
@cpp Double(a) @ce over the range, so e.g. @cpp 135 @ce becomes @cpp 135.0 @ce.
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 Numbers with more than 52 bits of precision will not be represented
accurately when cast into a @relativeref{Magnum,Double}.
@see @ref castInto(const Corrade::Containers::StridedArrayView2D<const Double>&, const Corrade::Containers::StridedArrayView2D<UnsignedByte>&),
@ref Corrade::Containers::StridedArrayView::isContiguous()
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Double>& dst);
/** /**
@brief Cast 32-bit floating-point values into an integer representation @brief Cast 32-bit floating-point values into an integer representation
@param[in] src Source float values @param[in] src Source float values
@ -265,6 +315,56 @@ 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 64-bit floating-point values into an integer representation
@param[in] src Source double values
@param[out] dst Destination integral values
@m_since_latest
Unlike @ref packInto(), this function performs only an equivalent of
@cpp T(a) @ce over the range, so e.g. @cpp 135.0 @ce becomes @cpp 135 @ce.
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 Fractional part of the @relativeref{Magnum,Double} input will be
silently discarded when cast into an integer type.
@see @ref castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>&, const Corrade::Containers::StridedArrayView2D<Double>&),
@ref Corrade::Containers::StridedArrayView::isContiguous()
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst);
/**
* @overload
* @m_since_latest
*/
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Double>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst);
/** /**
@brief Cast integer values into a differently sized type @brief Cast integer values into a differently sized type
@param[in] src Source values @param[in] src Source values

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

@ -51,8 +51,8 @@ struct PackingBatchTest: Corrade::TestSuite::Tester {
void unpackHalf(); void unpackHalf();
void packHalf(); void packHalf();
template<class T> void castUnsignedFloat(); template<class FloatingPoint, class Integral> void castUnsignedFloatingPoint();
template<class T> void castSignedFloat(); template<class FloatingPoint, class Integral> void castSignedFloatingPoint();
template<class T, class U> void castUnsignedInteger(); template<class T, class U> void castUnsignedInteger();
template<class T, class U> void castSignedInteger(); template<class T, class U> void castSignedInteger();
@ -77,12 +77,18 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::unpackHalf, &PackingBatchTest::unpackHalf,
&PackingBatchTest::packHalf, &PackingBatchTest::packHalf,
&PackingBatchTest::castUnsignedFloat<UnsignedByte>, &PackingBatchTest::castUnsignedFloatingPoint<Float, UnsignedByte>,
&PackingBatchTest::castUnsignedFloat<UnsignedShort>, &PackingBatchTest::castUnsignedFloatingPoint<Float, UnsignedShort>,
&PackingBatchTest::castUnsignedFloat<UnsignedInt>, &PackingBatchTest::castUnsignedFloatingPoint<Float, UnsignedInt>,
&PackingBatchTest::castSignedFloat<Byte>, &PackingBatchTest::castUnsignedFloatingPoint<Double, UnsignedByte>,
&PackingBatchTest::castSignedFloat<Short>, &PackingBatchTest::castUnsignedFloatingPoint<Double, UnsignedShort>,
&PackingBatchTest::castSignedFloat<Int>, &PackingBatchTest::castUnsignedFloatingPoint<Double, UnsignedInt>,
&PackingBatchTest::castSignedFloatingPoint<Float, Byte>,
&PackingBatchTest::castSignedFloatingPoint<Float, Short>,
&PackingBatchTest::castSignedFloatingPoint<Float, Int>,
&PackingBatchTest::castSignedFloatingPoint<Double, Byte>,
&PackingBatchTest::castSignedFloatingPoint<Double, Short>,
&PackingBatchTest::castSignedFloatingPoint<Double, Int>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedShort>, &PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedShort>,
&PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedInt>, &PackingBatchTest::castUnsignedInteger<UnsignedByte, UnsignedInt>,
@ -109,6 +115,12 @@ PackingBatchTest::PackingBatchTest() {
&PackingBatchTest::assertionsCast<Float, Short>, &PackingBatchTest::assertionsCast<Float, Short>,
&PackingBatchTest::assertionsCast<Float, UnsignedInt>, &PackingBatchTest::assertionsCast<Float, UnsignedInt>,
&PackingBatchTest::assertionsCast<Float, Int>, &PackingBatchTest::assertionsCast<Float, Int>,
&PackingBatchTest::assertionsCast<Double, UnsignedByte>,
&PackingBatchTest::assertionsCast<Double, Byte>,
&PackingBatchTest::assertionsCast<Double, UnsignedShort>,
&PackingBatchTest::assertionsCast<Double, Short>,
&PackingBatchTest::assertionsCast<Double, UnsignedInt>,
&PackingBatchTest::assertionsCast<Double, Int>,
&PackingBatchTest::assertionsCast<UnsignedShort, UnsignedByte>, &PackingBatchTest::assertionsCast<UnsignedShort, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedByte>, &PackingBatchTest::assertionsCast<UnsignedInt, UnsignedByte>,
&PackingBatchTest::assertionsCast<UnsignedInt, UnsignedShort>, &PackingBatchTest::assertionsCast<UnsignedInt, UnsignedShort>,
@ -433,12 +445,12 @@ 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::castUnsignedFloat() { template<class FloatingPoint, class Integral> void PackingBatchTest::castUnsignedFloatingPoint() {
setTestCaseTemplateName(TypeTraits<T>::name()); setTestCaseTemplateName({TypeTraits<FloatingPoint>::name(), TypeTraits<Integral>::name()});
struct Data { struct Data {
Math::Vector2<T> src; Math::Vector2<Integral> src;
Vector2 dst; Math::Vector2<FloatingPoint> dst;
} data[]{ } data[]{
{{0, 89}, {}}, {{0, 89}, {}},
{{149, 22}, {}}, {{149, 22}, {}},
@ -447,38 +459,38 @@ template<class T> void PackingBatchTest::castUnsignedFloat() {
/* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type /* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type
const Vector2 [3] with a compound literal), wtf */ const Vector2 [3] with a compound literal), wtf */
const Vector2 expectedFloat[] { const Math::Vector2<FloatingPoint> expectedFloatingPoint[] {
{0.0f, 89.0f}, {FloatingPoint(0.0), FloatingPoint(89.0)},
{149.0f, 22.0f}, {FloatingPoint(149.0), FloatingPoint(22.0)},
{13.0f, 255.0f} {FloatingPoint(13.0), FloatingPoint(255.0)}
}; };
constexpr Math::Vector2<T> expectedInteger[] { constexpr Math::Vector2<Integral> expectedIntegral[] {
{0, 89}, {0, 89},
{149, 22}, {149, 22},
{13, 255} {13, 255}
}; };
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)}; Corrade::Containers::StridedArrayView1D<Math::Vector2<Integral>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; Corrade::Containers::StridedArrayView1D<Math::Vector2<FloatingPoint>> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, T>(src), castInto(Corrade::Containers::arrayCast<2, Integral>(src),
Corrade::Containers::arrayCast<2, Float>(dst)); Corrade::Containers::arrayCast<2, FloatingPoint>(dst));
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloat), CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloatingPoint),
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
/* Test the other way around as well */ /* Test the other way around as well */
castInto(Corrade::Containers::arrayCast<2, Float>(dst), castInto(Corrade::Containers::arrayCast<2, FloatingPoint>(dst),
Corrade::Containers::arrayCast<2, T>(src)); Corrade::Containers::arrayCast<2, Integral>(src));
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedInteger), CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedIntegral),
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
} }
template<class T> void PackingBatchTest::castSignedFloat() { template<class FloatingPoint, class Integral> void PackingBatchTest::castSignedFloatingPoint() {
setTestCaseTemplateName(TypeTraits<T>::name()); setTestCaseTemplateName({TypeTraits<FloatingPoint>::name(), TypeTraits<Integral>::name()});
struct Data { struct Data {
Math::Vector2<T> src; Math::Vector2<Integral> src;
Vector2 dst; Math::Vector2<FloatingPoint> dst;
} data[]{ } data[]{
{{0, -89}, {}}, {{0, -89}, {}},
{{-119, 22}, {}}, {{-119, 22}, {}},
@ -487,29 +499,29 @@ template<class T> void PackingBatchTest::castSignedFloat() {
/* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type /* GCC 4.8 doesn't like constexpr here (cannot initialize aggregate of type
const Vector2 [3] with a compound literal), wtf */ const Vector2 [3] with a compound literal), wtf */
const Vector2 expectedFloat[] { const Math::Vector2<FloatingPoint> expectedFloatingPoint[] {
{0.0f, -89.0f}, {FloatingPoint(0.0), FloatingPoint(-89.0)},
{-119.0f, 22.0f}, {FloatingPoint(-119.0), FloatingPoint(22.0)},
{13.0f, 127.0f} {FloatingPoint(13.0), FloatingPoint(127.0)}
}; };
constexpr Math::Vector2<T> expectedInteger[] { constexpr Math::Vector2<Integral> expectedIntegral[] {
{0, -89}, {0, -89},
{-119, 22}, {-119, 22},
{13, 127} {13, 127}
}; };
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)}; Corrade::Containers::StridedArrayView1D<Math::Vector2<Integral>> src{data, &data[0].src, 3, sizeof(Data)};
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; Corrade::Containers::StridedArrayView1D<Math::Vector2<FloatingPoint>> dst{data, &data[0].dst, 3, sizeof(Data)};
castInto(Corrade::Containers::arrayCast<2, T>(src), castInto(Corrade::Containers::arrayCast<2, Integral>(src),
Corrade::Containers::arrayCast<2, Float>(dst)); Corrade::Containers::arrayCast<2, FloatingPoint>(dst));
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloat), CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloatingPoint),
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
/* Test the other way around as well */ /* Test the other way around as well */
castInto(Corrade::Containers::arrayCast<2, Float>(dst), castInto(Corrade::Containers::arrayCast<2, FloatingPoint>(dst),
Corrade::Containers::arrayCast<2, T>(src)); Corrade::Containers::arrayCast<2, Integral>(src));
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedInteger), CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedIntegral),
Corrade::TestSuite::Compare::Container); Corrade::TestSuite::Compare::Container);
} }

Loading…
Cancel
Save