mirror of https://github.com/mosra/magnum.git
6 changed files with 957 additions and 4 deletions
@ -0,0 +1,242 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "PackingBatch.h" |
||||||
|
|
||||||
|
#include <Corrade/Containers/StridedArrayView.h> |
||||||
|
#include <Corrade/Utility/Assert.h> |
||||||
|
|
||||||
|
#include "Magnum/Math/Packing.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Math { |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
template<class T> inline void unpackUnsignedIntoImplementation(const Corrade::Containers::StridedArrayView2D<const T>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
CORRADE_ASSERT(src.size() == dst.size(), |
||||||
|
"Math::unpackInto(): wrong destination size, got" << dst.size() << "but expected" << src.size(), ); |
||||||
|
CORRADE_ASSERT(src.template isContiguous<1>() && dst.isContiguous<1>(), |
||||||
|
"Math::unpackInto(): second view dimension is not contiguous", ); |
||||||
|
|
||||||
|
/** @todo SSE/NEON implementations exploiting second dimension size/stride,
|
||||||
|
contiguity etc */ |
||||||
|
|
||||||
|
/* Caching values to avoid inline function calls in ebug builds */ |
||||||
|
constexpr Float bitMax = Implementation::bitMax<T>(); |
||||||
|
const char* srcPtr = reinterpret_cast<const char*>(src.data()); |
||||||
|
char* dstPtr = reinterpret_cast<char*>(dst.data()); |
||||||
|
const std::ptrdiff_t srcStride = src.stride()[0]; |
||||||
|
const std::ptrdiff_t dstStride = dst.stride()[0]; |
||||||
|
const std::size_t maxJ = src.size()[1]; |
||||||
|
for(std::size_t i = 0, maxI = src.size()[0]; i != maxI; ++i) { |
||||||
|
const T* srcPtrI = reinterpret_cast<const T*>(srcPtr); |
||||||
|
Float* dstPtrI = reinterpret_cast<Float*>(dstPtr); |
||||||
|
for(std::size_t j = 0; j != maxJ; ++j) |
||||||
|
*dstPtrI++ = *srcPtrI++/bitMax; |
||||||
|
|
||||||
|
srcPtr += srcStride; |
||||||
|
dstPtr += dstStride; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void unpackInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
unpackUnsignedIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void unpackInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
unpackUnsignedIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
template<class T> inline void unpackSignedIntoImplementation(const Corrade::Containers::StridedArrayView2D<const T>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
CORRADE_ASSERT(src.size() == dst.size(), |
||||||
|
"Math::unpackInto(): wrong destination size, got" << dst.size() << "but expected" << src.size(), ); |
||||||
|
CORRADE_ASSERT(src.template isContiguous<1>() && dst.isContiguous<1>(), |
||||||
|
"Math::unpackInto(): second view dimension is not contiguous", ); |
||||||
|
|
||||||
|
/** @todo SSE/NEON implementations exploiting second dimension size/stride,
|
||||||
|
contiguity etc */ |
||||||
|
|
||||||
|
/* Caching values to avoid inline function calls in debug builds */ |
||||||
|
constexpr Float bitMax = Implementation::bitMax<T>(); |
||||||
|
const char* srcPtr = reinterpret_cast<const char*>(src.data()); |
||||||
|
char* dstPtr = reinterpret_cast<char*>(dst.data()); |
||||||
|
const std::ptrdiff_t srcStride = src.stride()[0]; |
||||||
|
const std::ptrdiff_t dstStride = dst.stride()[0]; |
||||||
|
const std::size_t maxJ = src.size()[1]; |
||||||
|
for(std::size_t i = 0, maxI = src.size()[0]; i != maxI; ++i) { |
||||||
|
const T* srcPtrI = reinterpret_cast<const T*>(srcPtr); |
||||||
|
Float* dstPtrI = reinterpret_cast<Float*>(dstPtr); |
||||||
|
for(std::size_t j = 0; j != maxJ; ++j) { |
||||||
|
const Float value = *srcPtrI++/bitMax; |
||||||
|
/* Avoiding a max() call in Debug */ |
||||||
|
*dstPtrI++ = value < -1.0f ? -1.0f : value; |
||||||
|
} |
||||||
|
|
||||||
|
srcPtr += srcStride; |
||||||
|
dstPtr += dstStride; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void unpackInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
unpackSignedIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void unpackInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
unpackSignedIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
template<class T> inline void packIntoImplementation(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<T>& dst) { |
||||||
|
CORRADE_ASSERT(src.size() == dst.size(), |
||||||
|
"Math::packInto(): wrong destination size, got" << dst.size() << "but expected" << src.size(), ); |
||||||
|
CORRADE_ASSERT(src.isContiguous<1>() && dst.template isContiguous<1>(), |
||||||
|
"Math::packInto(): second view dimension is not contiguous", ); |
||||||
|
|
||||||
|
/** @todo SSE/NEON implementations exploiting second dimension size/stride,
|
||||||
|
contiguity etc */ |
||||||
|
|
||||||
|
/* Caching values to avoid inline function calls in debug builds */ |
||||||
|
constexpr Float bitMax = Implementation::bitMax<T>(); |
||||||
|
const char* srcPtr = reinterpret_cast<const char*>(src.data()); |
||||||
|
char* dstPtr = reinterpret_cast<char*>(dst.data()); |
||||||
|
const std::ptrdiff_t srcStride = src.stride()[0]; |
||||||
|
const std::ptrdiff_t dstStride = dst.stride()[0]; |
||||||
|
const std::size_t maxJ = src.size()[1]; |
||||||
|
for(std::size_t i = 0, maxI = src.size()[0]; i != maxI; ++i) { |
||||||
|
const Float* srcPtrI = reinterpret_cast<const Float*>(srcPtr); |
||||||
|
T* dstPtrI = reinterpret_cast<T*>(dstPtr); |
||||||
|
for(std::size_t j = 0; j != maxJ; ++j) |
||||||
|
/** @todo provide a version that doesn't do rounding */ |
||||||
|
*dstPtrI++ = std::round(*srcPtrI++*bitMax); |
||||||
|
|
||||||
|
srcPtr += srcStride; |
||||||
|
dstPtr += dstStride; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) { |
||||||
|
packIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) { |
||||||
|
packIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst) { |
||||||
|
packIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst) { |
||||||
|
packIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
template<class T, class U> inline void castIntoImplementation(const Corrade::Containers::StridedArrayView2D<const T>& src, const Corrade::Containers::StridedArrayView2D<U>& dst) { |
||||||
|
CORRADE_ASSERT(src.size() == dst.size(), |
||||||
|
"Math::castInto(): wrong destination size, got" << dst.size() << "but expected" << src.size(), ); |
||||||
|
CORRADE_ASSERT(src.template isContiguous<1>() && dst.template isContiguous<1>(), |
||||||
|
"Math::castInto(): second view dimension is not contiguous", ); |
||||||
|
|
||||||
|
/** @todo SSE/NEON implementations exploiting second dimension size/stride,
|
||||||
|
contiguity etc */ |
||||||
|
|
||||||
|
/* Caching values to avoid inline function calls in debug buílds */ |
||||||
|
const char* srcPtr = reinterpret_cast<const char*>(src.data()); |
||||||
|
char* dstPtr = reinterpret_cast<char*>(dst.data()); |
||||||
|
const std::ptrdiff_t srcStride = src.stride()[0]; |
||||||
|
const std::ptrdiff_t dstStride = dst.stride()[0]; |
||||||
|
const std::size_t maxJ = src.size()[1]; |
||||||
|
for(std::size_t i = 0, maxI = src.size()[0]; i != maxI; ++i) { |
||||||
|
const T* srcPtrI = reinterpret_cast<const T*>(srcPtr); |
||||||
|
U* dstPtrI = reinterpret_cast<U*>(dstPtr); |
||||||
|
for(std::size_t j = 0; j != maxJ; ++j) |
||||||
|
*dstPtrI++ = U(*srcPtrI++); |
||||||
|
|
||||||
|
srcPtr += srcStride; |
||||||
|
dstPtr += dstStride; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst) { |
||||||
|
castIntoImplementation(src, dst); |
||||||
|
} |
||||||
|
|
||||||
|
}} |
||||||
@ -0,0 +1,234 @@ |
|||||||
|
#ifndef Magnum_Math_PackingBatch_h |
||||||
|
#define Magnum_Math_PackingBatch_h |
||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Functions @ref Magnum::Math::packInto(), @ref Magnum::Math::unpackInto(), @ref Magnum::Math::castInto() |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <Corrade/Containers/Containers.h> |
||||||
|
|
||||||
|
#include "Magnum/Types.h" |
||||||
|
#include "Magnum/visibility.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Math { |
||||||
|
|
||||||
|
/**
|
||||||
|
@{ @name Batch packing functions |
||||||
|
|
||||||
|
These functions process an ubounded range of values, as opposed to single |
||||||
|
vectors or scalars. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Unpack unsigned integral values into a floating-point representation |
||||||
|
@param[in] src Source integral values |
||||||
|
@param[out] dst Destination floating-point values |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Converts integral values from full range of given *unsigned* integral type to |
||||||
|
floating-point values in range @f$ [0, 1] @f$. 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. |
||||||
|
@see @ref packInto(), @ref castInto(), |
||||||
|
@ref Corrade::Containers::StridedArrayView::isContiguous() |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void unpackInto(const Corrade::Containers::StridedArrayView2D<const UnsignedByte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void unpackInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Unpack signed integral values into a floating-point representation |
||||||
|
@param[in] src Source integral values |
||||||
|
@param[out] dst Destination floating-point values |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Converts integral values from full range of given *signed* integral type to |
||||||
|
floating-point values in range @f$ [-1, 1] @f$. 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. |
||||||
|
@see @ref packInto(), @ref castInto(), |
||||||
|
@ref Corrade::Containers::StridedArrayView::isContiguous() |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void unpackInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void unpackInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Pack floating-point values into an integer representation |
||||||
|
@param[in] src Source floating-point values |
||||||
|
@param[out] dst Destination integral values |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Converts floating-point value in range @f$ [0, 1] @f$ to full range of |
||||||
|
given *unsigned* integral type or range @f$ [-1, 1] @f$ to full range of |
||||||
|
given *signed* integral type. 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 Conversion result for floating-point numbers outside the normalized |
||||||
|
range is undefined. |
||||||
|
|
||||||
|
@see @ref unpackInto(), @ref castInto(), |
||||||
|
@ref Corrade::Containers::StridedArrayView::isContiguous() |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void packInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Cast integer values into a floating-point representation |
||||||
|
@param[in] src Source integral values |
||||||
|
@param[out] dst Destination floating-point values |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Unlike @ref packInto(), this function performs only an equivalent of |
||||||
|
@cpp Float(a) @ce over the range, so e.g. @cpp 135 @ce becomes @cpp 135.0f @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 23 bits of precision will not be represented |
||||||
|
accurately when cast into a @ref Magnum::Float "Float". |
||||||
|
|
||||||
|
@see @ref castInto(const Corrade::Containers::StridedArrayView2D<const Float>&, 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<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Byte>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedShort>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Short>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const UnsignedInt>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Int>& src, const Corrade::Containers::StridedArrayView2D<Float>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Cast floating-point values into an integer representation |
||||||
|
@param[in] src Source floating-point values |
||||||
|
@param[out] dst Destination integral values |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Unlike @ref packInto(), this function performs only an equivalent of |
||||||
|
@cpp Float(a) @ce over the range, so e.g. @cpp 135 @ce becomes @cpp 135.0f @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 23 bits of precision will not be represented |
||||||
|
accurately when cast into a @ref Magnum::Float "Float". |
||||||
|
|
||||||
|
@see @ref castInto(const Corrade::Containers::StridedArrayView2D<const Float>&, const Corrade::Containers::StridedArrayView2D<UnsignedByte>&), |
||||||
|
@ref Corrade::Containers::StridedArrayView::isContiguous() |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedByte>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Byte>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedShort>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Short>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<UnsignedInt>& dst); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @overload |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D<const Float>& src, const Corrade::Containers::StridedArrayView2D<Int>& dst); |
||||||
|
|
||||||
|
/*@}*/ |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,469 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
#include <Corrade/Containers/StridedArrayView.h> |
||||||
|
#include <Corrade/TestSuite/Tester.h> |
||||||
|
#include <Corrade/TestSuite/Compare/Container.h> |
||||||
|
#include <Corrade/Utility/DebugStl.h> |
||||||
|
|
||||||
|
#include "Magnum/Math/Color.h" |
||||||
|
#include "Magnum/Math/Packing.h" |
||||||
|
#include "Magnum/Math/PackingBatch.h" |
||||||
|
#include "Magnum/Math/Vector4.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Math { namespace Test { namespace { |
||||||
|
|
||||||
|
struct PackingBatchTest: Corrade::TestSuite::Tester { |
||||||
|
explicit PackingBatchTest(); |
||||||
|
|
||||||
|
void unpackUnsignedByte(); |
||||||
|
void unpackUnsignedShort(); |
||||||
|
void unpackSignedByte(); |
||||||
|
void unpackSignedShort(); |
||||||
|
void packUnsignedByte(); |
||||||
|
void packUnsignedShort(); |
||||||
|
void packSignedByte(); |
||||||
|
void packSignedShort(); |
||||||
|
|
||||||
|
template<class T> void castUnsigned(); |
||||||
|
template<class T> void castSigned(); |
||||||
|
|
||||||
|
template<class T> void assertionsPackUnpack(); |
||||||
|
template<class T> void assertionsCast(); |
||||||
|
}; |
||||||
|
|
||||||
|
PackingBatchTest::PackingBatchTest() { |
||||||
|
addTests({&PackingBatchTest::unpackUnsignedByte, |
||||||
|
&PackingBatchTest::unpackUnsignedShort, |
||||||
|
&PackingBatchTest::unpackSignedByte, |
||||||
|
&PackingBatchTest::unpackSignedShort, |
||||||
|
&PackingBatchTest::packUnsignedByte, |
||||||
|
&PackingBatchTest::packUnsignedShort, |
||||||
|
&PackingBatchTest::packSignedByte, |
||||||
|
&PackingBatchTest::packSignedShort, |
||||||
|
|
||||||
|
&PackingBatchTest::castUnsigned<UnsignedByte>, |
||||||
|
&PackingBatchTest::castUnsigned<UnsignedShort>, |
||||||
|
&PackingBatchTest::castUnsigned<UnsignedInt>, |
||||||
|
&PackingBatchTest::castSigned<Byte>, |
||||||
|
&PackingBatchTest::castSigned<Short>, |
||||||
|
&PackingBatchTest::castSigned<Int>, |
||||||
|
|
||||||
|
&PackingBatchTest::assertionsPackUnpack<UnsignedByte>, |
||||||
|
&PackingBatchTest::assertionsPackUnpack<Byte>, |
||||||
|
&PackingBatchTest::assertionsPackUnpack<UnsignedShort>, |
||||||
|
&PackingBatchTest::assertionsPackUnpack<Short>, |
||||||
|
&PackingBatchTest::assertionsCast<UnsignedByte>, |
||||||
|
&PackingBatchTest::assertionsCast<Byte>, |
||||||
|
&PackingBatchTest::assertionsCast<UnsignedShort>, |
||||||
|
&PackingBatchTest::assertionsCast<Short>, |
||||||
|
&PackingBatchTest::assertionsCast<UnsignedInt>, |
||||||
|
&PackingBatchTest::assertionsCast<Int>}); |
||||||
|
} |
||||||
|
|
||||||
|
typedef Math::Vector2<UnsignedByte> Vector2ub; |
||||||
|
typedef Math::Vector2<UnsignedShort> Vector2us; |
||||||
|
typedef Math::Vector2<Byte> Vector2b; |
||||||
|
typedef Math::Vector2<Short> Vector2s; |
||||||
|
typedef Math::Vector2<Float> Vector2; |
||||||
|
typedef Math::Vector3<Float> Vector3; |
||||||
|
typedef Math::Vector4<Float> Vector4; |
||||||
|
|
||||||
|
void PackingBatchTest::unpackUnsignedByte() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2ub src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, 89}, {}}, |
||||||
|
{{149, 255}, {}}, |
||||||
|
{{0, 255}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expected[] { |
||||||
|
{0.0f, 0.34902f}, |
||||||
|
{0.584314f, 1.0f}, |
||||||
|
{0.0f, 1.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2ub> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
unpackInto(Corrade::Containers::arrayCast<2, UnsignedByte>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::unpack<Vector2>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::unpackUnsignedShort() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2us src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, 8192}, {}}, |
||||||
|
{{49152, 65535}, {}}, |
||||||
|
{{0, 65535}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expected[] { |
||||||
|
{0.0f, 0.125002f}, |
||||||
|
{0.750011f, 1.0f}, |
||||||
|
{0.0f, 1.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2us> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
unpackInto(Corrade::Containers::arrayCast<2, UnsignedShort>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::unpack<Vector2>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::unpackSignedByte() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2b src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, 127}, {}}, |
||||||
|
{{37, -72}, {}}, |
||||||
|
{{-127, -128}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expected[] { |
||||||
|
{0.0f, 1.0f}, |
||||||
|
{0.291339f, -0.566929f}, |
||||||
|
{-1.0f, -1.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2b> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
unpackInto(Corrade::Containers::arrayCast<2, Byte>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::unpack<Vector2>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::unpackSignedShort() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2s src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, 16384}, {}}, |
||||||
|
{{-16384, 32767}, {}}, |
||||||
|
{{-32767, -32768}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expected[] { |
||||||
|
{0.0f, 0.500015f}, |
||||||
|
{-0.500015f, 1.0f}, |
||||||
|
{-1.0f, -1.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2s> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
unpackInto(Corrade::Containers::arrayCast<2, Short>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::unpack<Vector2>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::packUnsignedByte() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2 src; |
||||||
|
Vector2ub dst; |
||||||
|
} data[]{ |
||||||
|
{{0.0f, 0.0000001f}, {}}, |
||||||
|
{{0.4357f, 0.5f}, {}}, |
||||||
|
{{1.0f, 0.9999999f}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2ub expected[] { |
||||||
|
{0, 0}, |
||||||
|
{111, 128}, |
||||||
|
{255, 255} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2ub> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
packInto(Corrade::Containers::arrayCast<2, Float>(src), |
||||||
|
Corrade::Containers::arrayCast<2, UnsignedByte>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::pack<Vector2ub>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::packUnsignedShort() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2 src; |
||||||
|
Vector2us dst; |
||||||
|
} data[]{ |
||||||
|
{{0.0f, 0.0000001f}, {}}, |
||||||
|
{{0.4357f, 0.5f}, {}}, |
||||||
|
{{1.0f, 0.9999999f}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2us expected[] { |
||||||
|
{0, 0}, |
||||||
|
{28554, 32768}, |
||||||
|
{65535, 65535} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2us> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
packInto(Corrade::Containers::arrayCast<2, Float>(src), |
||||||
|
Corrade::Containers::arrayCast<2, UnsignedShort>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::pack<Vector2us>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::packSignedByte() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2 src; |
||||||
|
Vector2b dst; |
||||||
|
} data[]{ |
||||||
|
{{-1.0f, -0.732f}, {}}, |
||||||
|
{{0.0f, 0.1357f}, {}}, |
||||||
|
{{1.0f, 0.9999999f}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2b expected[] { |
||||||
|
{-127, -93}, |
||||||
|
{0, 17}, |
||||||
|
{127, 127} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2b> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
packInto(Corrade::Containers::arrayCast<2, Float>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Byte>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::pack<Vector2b>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
void PackingBatchTest::packSignedShort() { |
||||||
|
/* Test data adapted from PackingTest */ |
||||||
|
struct Data { |
||||||
|
Vector2 src; |
||||||
|
Vector2s dst; |
||||||
|
} data[]{ |
||||||
|
{{-1.0f, -0.33f}, {}}, |
||||||
|
{{0.0f, 0.66f}, {}}, |
||||||
|
{{1.0f, 0.9999999f}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2s expected[] { |
||||||
|
{-32767, -10813}, |
||||||
|
{0, 21626}, |
||||||
|
{32767, 32767} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2s> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
packInto(Corrade::Containers::arrayCast<2, Float>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Short>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expected), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Ensure the results are consistent with non-batch APIs */ |
||||||
|
for(std::size_t i = 0; i != Corrade::Containers::arraySize(data); ++i) |
||||||
|
CORRADE_COMPARE(Math::pack<Vector2s>(data[i].src), data[i].dst); |
||||||
|
} |
||||||
|
|
||||||
|
template<class T> void PackingBatchTest::castUnsigned() { |
||||||
|
setTestCaseTemplateName(TypeTraits<T>::name()); |
||||||
|
|
||||||
|
struct Data { |
||||||
|
Math::Vector2<T> src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, 89}, {}}, |
||||||
|
{{149, 22}, {}}, |
||||||
|
{{13, 255}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expectedFloat[] { |
||||||
|
{0.0f, 89.0f}, |
||||||
|
{149.0f, 22.0f}, |
||||||
|
{13.0f, 255.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Math::Vector2<T> expectedInteger[] { |
||||||
|
{0, 89}, |
||||||
|
{149, 22}, |
||||||
|
{13, 255} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
castInto(Corrade::Containers::arrayCast<2, T>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloat), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Test the other way around as well */ |
||||||
|
castInto(Corrade::Containers::arrayCast<2, Float>(dst), |
||||||
|
Corrade::Containers::arrayCast<2, T>(src)); |
||||||
|
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedInteger), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
} |
||||||
|
|
||||||
|
template<class T> void PackingBatchTest::castSigned() { |
||||||
|
setTestCaseTemplateName(TypeTraits<T>::name()); |
||||||
|
|
||||||
|
struct Data { |
||||||
|
Math::Vector2<T> src; |
||||||
|
Vector2 dst; |
||||||
|
} data[]{ |
||||||
|
{{0, -89}, {}}, |
||||||
|
{{-119, 22}, {}}, |
||||||
|
{{13, 127}, {}} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Vector2 expectedFloat[] { |
||||||
|
{0.0f, -89.0f}, |
||||||
|
{-119.0f, 22.0f}, |
||||||
|
{13.0f, 127.0f} |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr Math::Vector2<T> expectedInteger[] { |
||||||
|
{0, -89}, |
||||||
|
{-119, 22}, |
||||||
|
{13, 127} |
||||||
|
}; |
||||||
|
|
||||||
|
Corrade::Containers::StridedArrayView1D<Math::Vector2<T>> src{data, &data[0].src, 3, sizeof(Data)}; |
||||||
|
Corrade::Containers::StridedArrayView1D<Vector2> dst{data, &data[0].dst, 3, sizeof(Data)}; |
||||||
|
castInto(Corrade::Containers::arrayCast<2, T>(src), |
||||||
|
Corrade::Containers::arrayCast<2, Float>(dst)); |
||||||
|
CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedFloat), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
|
||||||
|
/* Test the other way around as well */ |
||||||
|
castInto(Corrade::Containers::arrayCast<2, Float>(dst), |
||||||
|
Corrade::Containers::arrayCast<2, T>(src)); |
||||||
|
CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedInteger), |
||||||
|
Corrade::TestSuite::Compare::Container); |
||||||
|
} |
||||||
|
|
||||||
|
template<class T> void PackingBatchTest::assertionsPackUnpack() { |
||||||
|
Math::Vector2<T> data[2]{}; |
||||||
|
Vector2 resultWrongCount[1]{}; |
||||||
|
Vector3 resultWrongVectorSize[2]{}; |
||||||
|
Vector4 resultNonContiguous[2]{}; |
||||||
|
|
||||||
|
auto src = Corrade::Containers::arrayCast<2, T>( |
||||||
|
Corrade::Containers::arrayView(data)); |
||||||
|
auto dstWrongCount = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultWrongCount)); |
||||||
|
auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultWrongVectorSize)); |
||||||
|
auto dstNotContiguous = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultNonContiguous)).every({1, 2}); |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
unpackInto(src, dstWrongCount); |
||||||
|
unpackInto(src, dstWrongVectorSize); |
||||||
|
unpackInto(src, dstNotContiguous); |
||||||
|
packInto(dstWrongCount, src); |
||||||
|
packInto(dstWrongVectorSize, src); |
||||||
|
packInto(dstNotContiguous, src); |
||||||
|
CORRADE_COMPARE(out.str(), |
||||||
|
"Math::unpackInto(): wrong destination size, got {1, 2} but expected {2, 2}\n" |
||||||
|
"Math::unpackInto(): wrong destination size, got {2, 3} but expected {2, 2}\n" |
||||||
|
"Math::unpackInto(): second view dimension is not contiguous\n" |
||||||
|
"Math::packInto(): wrong destination size, got {2, 2} but expected {1, 2}\n" |
||||||
|
"Math::packInto(): wrong destination size, got {2, 2} but expected {2, 3}\n" |
||||||
|
"Math::packInto(): second view dimension is not contiguous\n"); |
||||||
|
} |
||||||
|
|
||||||
|
template<class T> void PackingBatchTest::assertionsCast() { |
||||||
|
Math::Vector2<T> data[2]{}; |
||||||
|
Vector2 resultWrongCount[1]{}; |
||||||
|
Vector3 resultWrongVectorSize[2]{}; |
||||||
|
Vector4 resultNonContiguous[2]{}; |
||||||
|
|
||||||
|
auto src = Corrade::Containers::arrayCast<2, T>( |
||||||
|
Corrade::Containers::arrayView(data)); |
||||||
|
auto dstWrongCount = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultWrongCount)); |
||||||
|
auto dstWrongVectorSize = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultWrongVectorSize)); |
||||||
|
auto dstNotContiguous = Corrade::Containers::arrayCast<2, Float>( |
||||||
|
Corrade::Containers::arrayView(resultNonContiguous)).every({1, 2}); |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
castInto(src, dstWrongCount); |
||||||
|
castInto(src, dstWrongVectorSize); |
||||||
|
castInto(src, dstNotContiguous); |
||||||
|
castInto(dstWrongCount, src); |
||||||
|
castInto(dstWrongVectorSize, src); |
||||||
|
castInto(dstNotContiguous, src); |
||||||
|
CORRADE_COMPARE(out.str(), |
||||||
|
"Math::castInto(): wrong destination size, got {1, 2} but expected {2, 2}\n" |
||||||
|
"Math::castInto(): wrong destination size, got {2, 3} but expected {2, 2}\n" |
||||||
|
"Math::castInto(): second view dimension is not contiguous\n" |
||||||
|
"Math::castInto(): wrong destination size, got {2, 2} but expected {1, 2}\n" |
||||||
|
"Math::castInto(): wrong destination size, got {2, 2} but expected {2, 3}\n" |
||||||
|
"Math::castInto(): second view dimension is not contiguous\n"); |
||||||
|
} |
||||||
|
|
||||||
|
}}}} |
||||||
|
|
||||||
|
CORRADE_TEST_MAIN(Magnum::Math::Test::PackingBatchTest) |
||||||
Loading…
Reference in new issue