Browse Source

Math: return an array reference instead of a pointer from data().

This makes it possible to conveniently do things like

    Containers::StridedArrayView1D<Float> array = …;
    Vector4 vector{NoInit};
    Utility::copy(array, vector); // or the other way around

which is especially useful together with the new JSON classes. In some
cases this means the function is no longer constexpr, but those weren't
constexpr because it was useful for anything, they were only because it
was possible. So this breakage shouldn't do any harm I think.
pull/554/head
Vladimír Vondruš 4 years ago
parent
commit
d474f9d176
  1. 16
      doc/changelog.dox
  2. 15
      src/Magnum/Math/Bezier.h
  3. 15
      src/Magnum/Math/BoolVector.h
  4. 26
      src/Magnum/Math/Complex.h
  5. 24
      src/Magnum/Math/CubicHermite.h
  6. 24
      src/Magnum/Math/Dual.h
  7. 20
      src/Magnum/Math/DualComplex.h
  8. 20
      src/Magnum/Math/DualQuaternion.h
  9. 30
      src/Magnum/Math/Frustum.h
  10. 29
      src/Magnum/Math/Quaternion.h
  11. 40
      src/Magnum/Math/Range.h
  12. 30
      src/Magnum/Math/RectangularMatrix.h
  13. 13
      src/Magnum/Math/Test/BezierTest.cpp
  14. 39
      src/Magnum/Math/Test/BoolVectorTest.cpp
  15. 12
      src/Magnum/Math/Test/ComplexTest.cpp
  16. 48
      src/Magnum/Math/Test/CubicHermiteTest.cpp
  17. 12
      src/Magnum/Math/Test/DualComplexTest.cpp
  18. 15
      src/Magnum/Math/Test/DualQuaternionTest.cpp
  19. 12
      src/Magnum/Math/Test/DualTest.cpp
  20. 31
      src/Magnum/Math/Test/FrustumTest.cpp
  21. 15
      src/Magnum/Math/Test/QuaternionTest.cpp
  22. 45
      src/Magnum/Math/Test/RangeTest.cpp
  23. 41
      src/Magnum/Math/Test/RectangularMatrixTest.cpp
  24. 26
      src/Magnum/Math/Test/VectorTest.cpp
  25. 15
      src/Magnum/Math/Vector.h

16
doc/changelog.dox

@ -385,6 +385,15 @@ See also:
matrices, and with the default on @ref Math::RectangularMatrix being
zero-fill while @ref Math::Matrix stays with the identity for consistency
with other constructors.
- @ref Math::Bezier::data(), @ref Math::BoolVector::data(),
@ref Math::Complex::data(), @ref Math::CubicHermite::data(),
@ref Math::Dual::data(), @ref Math::DualComplex::data(),
@ref Math::DualQuaternion::data(), @ref Math::Frustum::data(),
@ref Math::Quaternion::data(), @ref Math::Range::data(),
@ref Math::RectangularMatrix::data() and @ref Math::Vector::data() now
return a reference to a fixed-size array instead of a pointer (i.e.,
@cpp T(&)[size] @ce instead of @cpp T* @ce) for more convenient usage in
APIs that take sized views.
@subsubsection changelog-latest-changes-meshtools MeshTools library
@ -946,6 +955,13 @@ See also:
process. Existing code that calls these with unsanitized inputs now
additionally needs to account for reflection as suggested in the
documentation.
- @ref Math::Complex::data(), @ref Math::CubicHermite::data(),
@ref Math::Dual::data(), @ref Math::DualComplex::data(),
@ref Math::DualQuaternion::data(), @ref Math::Frustum::data(),
@ref Math::Quaternion::data(), @ref Math::Range::data() and
@ref Math::RectangularMatrix::data() are no longer @cpp constexpr @ce in
order to make them return a reference to a fixed-size array instead of a
pointer, which was deemed a more useful property.
- @ref SceneGraph::Object::addChild() no longer requires the type constructor
to have the last parameter a parent object object pointer, as that was
quite limiting. Instead it's calling @ref SceneGraph::Object::setParent()

15
src/Magnum/Math/Bezier.h

@ -137,12 +137,21 @@ template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier {
/**
* @brief Raw data
* @return One-dimensional array of @cpp order + 1 @ce elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @cpp order + 1 @ce elements,
* i.e. @cpp T(&)[size] @ce.
* @see @ref operator[]()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
Vector<dimensions, T>* data() { return _data; }
constexpr const Vector<dimensions, T>* data() const { return _data; } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<dimensions, T>* data();
constexpr const Vector<dimensions, T>* data() const; /**< @overload */
#else
auto data() -> Vector<dimensions, T>(&)[order + 1] { return _data; }
constexpr auto data() const -> const Vector<dimensions, T>(&)[order + 1] { return _data; }
#endif
/** @brief Equality comparison */
bool operator==(const Bezier<order, dimensions, T>& other) const {

15
src/Magnum/Math/BoolVector.h

@ -130,12 +130,21 @@ template<std::size_t size> class BoolVector {
/**
* @brief Raw data
* @return Array of DataSize length
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @ref DataSize elements, i.e.
* @cpp UnsignedByte(&)[DataSize] @ce.
* @see @ref operator[](), @ref set()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
UnsignedByte* data() { return _data; }
constexpr const UnsignedByte* data() const { return _data; } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
UnsignedByte* data();
constexpr const UnsignedByte* data() const; /**< @overload */
#else
auto data() -> UnsignedByte(&)[DataSize] { return _data; }
constexpr auto data() const -> const UnsignedByte(&)[DataSize] { return _data; }
#endif
/** @brief Bit at given position */
constexpr bool operator[](std::size_t i) const {

26
src/Magnum/Math/Complex.h

@ -183,12 +183,30 @@ template<class T> class Complex {
/**
* @brief Raw data
* @return One-dimensional array of two elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of two elements, i.e.
* @cpp T(&)[2] @ce.
* @see @ref real(), @ref imaginary()
*/
T* data() { return &_real; }
constexpr const T* data() const { return &_real; } /**< @overload */
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[2] {
return reinterpret_cast<T(&)[2]>(_real);
}
/* Can't be constexpr anymore, the only other solution would be to
store `T _data[2]` instead of the two variables, but that may make
the internal implementation too error prone. Similarly as with
RectangularMatrix::data(), having a statically sized array returned
is a far more useful property than constexpr, so that wins. */
auto data() const -> const T(&)[2] {
return reinterpret_cast<const T(&)[2]>(_real);
}
#endif
/** @brief Equality comparison */
bool operator==(const Complex<T>& other) const {

24
src/Magnum/Math/CubicHermite.h

@ -146,12 +146,30 @@ template<class T> class CubicHermite {
/**
* @brief Raw data
* @return One-dimensional array of three elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of three elements, i.e.
* @cpp T(&)[3] @ce.
* @see @ref inTangent(), @ref point(), @ref outTangent()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return &_inTangent; }
constexpr const T* data() const { return &_inTangent; } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[3] {
return reinterpret_cast<T(&)[3]>(_inTangent);
}
/* Can't be constexpr anymore, the only other solution would be to
store `T _data[3]` instead of the three variables, but that may make
the internal implementation too error prone. Similarly as with
RectangularMatrix::data(), having a statically sized array returned
is a far more useful property than constexpr, so that wins. */
auto data() const -> const T(&)[3] {
return reinterpret_cast<const T(&)[3]>(_inTangent);
}
#endif
/** @brief Equality comparison */
bool operator==(const CubicHermite<T>& other) const;

24
src/Magnum/Math/Dual.h

@ -113,12 +113,30 @@ template<class T> class Dual {
/**
* @brief Raw data
* @return One-dimensional array of two elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of two elements, i.e.
* @cpp T(&)[2] @ce.
* @see @ref real(), @ref dual()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return &_real; }
constexpr const T* data() const { return &_real; } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[2] {
return reinterpret_cast<T(&)[2]>(_real);
}
/* Can't be constexpr anymore, the only other solution would be to
store `T _data[2]` instead of the two variables, but that may make
the internal implementation too error prone. Similarly as with
RectangularMatrix::data(), having a statically sized array returned
is a far more useful property than constexpr, so that wins. */
auto data() const -> const T(&)[2] {
return reinterpret_cast<const T(&)[2]>(_real);
}
#endif
/** @brief Equality comparison */
bool operator==(const Dual<T>& other) const {

20
src/Magnum/Math/DualComplex.h

@ -191,12 +191,26 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
/**
* @brief Raw data
* @return One-dimensional array of four elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of four elements, i.e.
* @cpp T(&)[4] @ce.
* @see @ref real(), @ref dual()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return Dual<Complex<T>>::data()->data(); }
constexpr const T* data() const { return Dual<Complex<T>>::data()->data(); } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[4] {
return reinterpret_cast<T(&)[4]>(Dual<Complex<T>>::data());
}
/* Can't be constexpr anymore, see base implementation for details */
auto data() const -> const T(&)[4] {
return reinterpret_cast<const T(&)[4]>(Dual<Complex<T>>::data());
}
#endif
/**
* @brief Whether the dual complex number is normalized

20
src/Magnum/Math/DualQuaternion.h

@ -338,12 +338,26 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/**
* @brief Raw data
* @return One-dimensional array of eight elements
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of eight elements, i.e.
* @cpp T(&)[8] @ce.
* @see @ref real(), @ref dual()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return Dual<Quaternion<T>>::data()->data(); }
constexpr const T* data() const { return Dual<Quaternion<T>>::data()->data(); } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[8] {
return reinterpret_cast<T(&)[8]>(Dual<Quaternion<T>>::data());
}
/* Can't be constexpr anymore, see base implementation for details */
auto data() const -> const T(&)[8] {
return reinterpret_cast<const T(&)[8]>(Dual<Quaternion<T>>::data());
}
#endif
/**
* @brief Whether the dual quaternion is normalized

30
src/Magnum/Math/Frustum.h

@ -127,10 +127,34 @@ template<class T> class Frustum {
/**
* @brief Raw data
* @return One-dimensional array of length `24`.
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of 24 elements, i.e.
* @cpp T(&)[24] @ce.
* @see @ref operator[]()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return _data[0].data(); }
constexpr const T* data() const { return _data[0].data(); } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[24] {
return reinterpret_cast<T(&)[24]>(_data);
}
/* Can't really be constexpr anymore, the only other solution is having
an union with `T _rawData[24]` and return that, but in a constexpr
context it'd mean we'd have to initialize it instead of `_data` in
the constructor ... and then operator[]() could not be constexpr
anymore. I can't think of a practical use case where constexpr
data() would be needed and operator[]() could not be used instead.
Similarly to RectangularMatrix::data(), having a statically sized
array returned is a far more useful property than constexpr, so that
wins. */
auto data() const -> const T(&)[24] {
return reinterpret_cast<const T(&)[24]>(_data);
}
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**

29
src/Magnum/Math/Quaternion.h

@ -362,12 +362,33 @@ template<class T> class Quaternion {
/**
* @brief Raw data
*
* Returns one-dimensional array of four elements, vector part first,
* scalar after.
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of four elements, i.e.
* @cpp T(&)[4] @ce, vector part first, scalar after.
* @see @ref vector(), @ref scalar()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return _vector.data(); }
constexpr const T* data() const { return _vector.data(); } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[4] {
return reinterpret_cast<T(&)[4]>(_vector);
}
/* Can't really be constexpr anymore, the only other solution is having
an union with `T _rawData[4]` and return that, but in a constexpr
context it'd mean we'd have to initialize it instead of `_data` in
the constructor ... and then operator[]() could not be constexpr
anymore. I can't think of a practical use case where constexpr
data() would be needed and operator[]() could not be used instead.
Similarly to RectangularMatrix::data(), having a statically sized
array returned is a far more useful property than constexpr, so that
wins. */
auto data() const -> const T(&)[4] {
return reinterpret_cast<const T(&)[4]>(_vector);
}
#endif
/** @brief Equality comparison */
bool operator==(const Quaternion<T>& other) const {

40
src/Magnum/Math/Range.h

@ -186,14 +186,34 @@ template<UnsignedInt dimensions, class T> class Range {
/**
* @brief Raw data
* @return One-dimensional array of `dimensions`*2 length.
*/
T* data() {
return dataInternal(typename std::conditional<dimensions == 1, void*, T*>::type{});
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @cpp dimensions*2 @ce elements,
* i.e. @cpp T(&)[dimensions*2] @ce.
* @ref min(), @ref max()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[dimensions*2] {
return reinterpret_cast<T(&)[dimensions*2]>(_min);
}
/* Can't really be constexpr anymore, the only other solution is having
an union with `T _rawData[24]` and return that, but in a constexpr
context it'd mean we'd have to initialize it instead of `_data` in
the constructor ... and then operator[]() could not be constexpr
anymore. I can't think of a practical use case where constexpr
data() would be needed and operator[]() could not be used instead.
Similarly to RectangularMatrix::data(), having a statically sized
array returned is a far more useful property than constexpr, so that
wins. */
auto data() const -> const T(&)[dimensions*2] {
return reinterpret_cast<const T(&)[dimensions*2]>(_min);
}
constexpr const T* data() const {
return dataInternal(typename std::conditional<dimensions == 1, void*, T*>::type{});
} /**< @overload */
#endif
/**
* @brief Minimal coordinates (inclusive)
@ -328,12 +348,6 @@ template<UnsignedInt dimensions, class T> class Range {
explicit Range(Magnum::NoInitT, Magnum::NoInitT*) noexcept: _min{Magnum::NoInit}, _max{Magnum::NoInit} {}
explicit Range(Magnum::NoInitT, void*) noexcept {}
/* Called from data(), always returning a T* */
constexpr const VectorType* dataInternal(void*) const { return &_min; }
VectorType* dataInternal(void*) { return &_min; }
constexpr const T* dataInternal(T*) const { return _min.data(); }
T* dataInternal(T*) { return _min.data(); }
VectorType _min, _max;
};

30
src/Magnum/Math/RectangularMatrix.h

@ -218,13 +218,33 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/**
* @brief Raw data
* @return One-dimensional array of `cols*rows` length in column-major
* order.
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of @cpp cols*rows @ce elements,
* i.e. @cpp T(&)[cols*rows] @ce.
* @see @ref operator[]()
*/
T* data() { return _data[0].data(); }
constexpr const T* data() const { return _data[0].data(); } /**< @overload */
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[cols*rows] {
return reinterpret_cast<T(&)[cols*rows]>(_data);
}
/* Can't really be constexpr anymore, the only other solution is having
an union with `T _rawData[cols*rows]` and return that, but in a
constexpr context it'd mean we'd have to initialize it instead of
`_data` in the constructor ... and then operator[]() could not be
constexpr anymore. I can't think of a practical use case where
constexpr data() would be needed and operator[]() could not be used
instead. Having a statically sized array returned is a far more
useful property than constexpr, so that wins. */
auto data() const -> const T(&)[cols*rows] {
return reinterpret_cast<const T(&)[cols*rows]>(_data);
}
#endif
/**
* @brief Column at given position

13
src/Magnum/Math/Test/BezierTest.cpp

@ -229,20 +229,23 @@ void BezierTest::data() {
CORRADE_COMPARE(a[2], (Vector2{0.7f, 20.3f}));
CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.0f, 0.0f}, Vector2{1.1f, 0.3f}, Vector2{0.7f, 20.3f}}));
constexpr QuadraticBezier2D b{Vector2{3.5f, 0.1f}, Vector2{1.3f, 10.3f}, Vector2{0.0f, -1.2f}};
constexpr QuadraticBezier2D ca{Vector2{3.5f, 0.1f}, Vector2{1.3f, 10.3f}, Vector2{0.0f, -1.2f}};
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */
constexpr
#endif
Vector2 c = b[2];
Vector2 c = ca[2];
CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */
constexpr
#endif
Vector2 d = *b.data();
Vector2 e = a.data()[2];
Vector2 d = *ca.data();
CORRADE_COMPARE(a.data()[2], (Vector2{0.7f, 20.3f}));
CORRADE_COMPARE(d, (Vector2{3.5f, 0.1f}));
CORRADE_COMPARE(e, (Vector2{0.7f, 20.3f}));
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void BezierTest::compare() {

39
src/Magnum/Math/Test/BoolVectorTest.cpp

@ -207,32 +207,37 @@ void BoolVectorTest::convert() {
void BoolVectorTest::data() {
/* 0b00001000, 0b00000011, 0b100 */
constexpr BoolVector19 a(0x08, 0x03, 0x04);
constexpr BoolVector19 ca(0x08, 0x03, 0x04);
CORRADE_VERIFY(!a[0] && !a[1] && !a[2]);
CORRADE_VERIFY(a[3]);
CORRADE_VERIFY(!a[4] && !a[5] && !a[6] && !a[7]);
CORRADE_VERIFY(a[8]);
CORRADE_VERIFY(a[9]);
CORRADE_VERIFY(!a[10] && !a[11] && !a[12] && !a[13] && !a[14] && !a[15] && !a[16] && !a[17]);
CORRADE_VERIFY(a[18]);
CORRADE_VERIFY(!ca[0] && !ca[1] && !ca[2]);
CORRADE_VERIFY(ca[3]);
CORRADE_VERIFY(!ca[4] && !ca[5] && !ca[6] && !ca[7]);
CORRADE_VERIFY(ca[8]);
CORRADE_VERIFY(ca[9]);
CORRADE_VERIFY(!ca[10] && !ca[11] && !ca[12] && !ca[13] && !ca[14] && !ca[15] && !ca[16] && !ca[17]);
CORRADE_VERIFY(ca[18]);
constexpr bool b = a[9];
constexpr bool b = ca[9];
CORRADE_COMPARE(b, true);
BoolVector19 a(0x08, 0x03, 0x04);
a.set(15, true);
CORRADE_VERIFY(a[15]);
CORRADE_COMPARE(a, BoolVector19(0x08, 0x83, 0x04));
a.set(15, false);
CORRADE_VERIFY(!a[15]);
CORRADE_COMPARE(a, BoolVector19(0x08, 0x03, 0x04));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
UnsignedByte c = *a.data();
UnsignedByte c = *ca.data();
CORRADE_COMPARE(a.data()[1], 0x03);
CORRADE_COMPARE(c, 0x08);
BoolVector19 d(0x08, 0x03, 0x04);
d.set(15, true);
CORRADE_VERIFY(d[15]);
CORRADE_COMPARE(d, BoolVector19(0x08, 0x83, 0x04));
d.set(15, false);
CORRADE_VERIFY(!d[15]);
CORRADE_COMPARE(d, BoolVector19(0x08, 0x03, 0x04));
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void BoolVectorTest::compare() {

12
src/Magnum/Math/Test/ComplexTest.cpp

@ -295,10 +295,14 @@ void ComplexTest::data() {
a.imaginary() = -3.5f;
CORRADE_COMPARE(a, (Complex{2.0f, -3.5f}));
constexpr Float b = *ca.data();
Float c = a.data()[1];
CORRADE_COMPARE(b, 1.5f);
CORRADE_COMPARE(c, -3.5f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[1], -3.5f);
CORRADE_COMPARE(*ca.data(), 1.5f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 2);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 2);
}
void ComplexTest::compare() {

48
src/Magnum/Math/Test/CubicHermiteTest.cpp

@ -672,10 +672,14 @@ void CubicHermiteTest::dataScalar() {
a.outTangent() = 2.1f;
CORRADE_COMPARE(a, (CubicHermite1D{3.0f, 1.0f, 2.1f}));
constexpr Float b = *ca.data();
Float c = a.data()[2];
CORRADE_COMPARE(b, 2.0f);
CORRADE_COMPARE(c, 2.1f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(*ca.data(), 2.0f);
CORRADE_COMPARE(a.data()[2], 2.1f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void CubicHermiteTest::dataVector() {
@ -693,10 +697,14 @@ void CubicHermiteTest::dataVector() {
a.outTangent().y() = 2.0f;
CORRADE_COMPARE(a, (CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}));
constexpr Vector2 b = *ca.data();
Vector2 c = a.data()[2];
CORRADE_COMPARE(b, (Vector2{1.0f, 2.0f}));
CORRADE_COMPARE(c, (Vector2{3.0f, 2.0f}));
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[2], (Vector2{3.0f, 2.0f}));
CORRADE_COMPARE(*ca.data(), (Vector2{1.0f, 2.0f}));
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void CubicHermiteTest::dataComplex() {
@ -714,10 +722,14 @@ void CubicHermiteTest::dataComplex() {
a.outTangent().imaginary() = 2.0f;
CORRADE_COMPARE(a, (CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}));
constexpr Complex b = *ca.data();
Complex c = a.data()[2];
CORRADE_COMPARE(b, (Complex{1.0f, 2.0f}));
CORRADE_COMPARE(c, (Complex{3.0f, 2.0f}));
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[2], (Complex{3.0f, 2.0f}));
CORRADE_COMPARE(*ca.data(), (Complex{1.0f, 2.0f}));
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void CubicHermiteTest::dataQuaternion() {
@ -745,10 +757,14 @@ void CubicHermiteTest::dataQuaternion() {
{{1.5f, -2.0f, 0.1f}, 1.0f},
{{3.0f, -0.5f, 2.0f}, 0.3f}}));
constexpr Quaternion b = *ca.data();
Quaternion c = a.data()[2];
CORRADE_COMPARE(b, (Quaternion{{1.0f, 2.0f, -1.0f}, 3.0f}));
CORRADE_COMPARE(c, (Quaternion{{3.0f, -0.5f, 2.0f}, 0.3f}));
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[2], (Quaternion{{3.0f, -0.5f, 2.0f}, 0.3f}));
CORRADE_COMPARE(*ca.data(), (Quaternion{{1.0f, 2.0f, -1.0f}, 3.0f}));
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
}
void CubicHermiteTest::compareScalar() {

12
src/Magnum/Math/Test/DualComplexTest.cpp

@ -288,10 +288,14 @@ void DualComplexTest::data() {
DualComplex a{{-1.0f, 2.5f}, {3.0f, -7.5f}};
constexpr Float d = *ca.data();
Float e = a.data()[3];
CORRADE_COMPARE(d, -1.0f);
CORRADE_COMPARE(e, -7.5f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(*ca.data(), -1.0f);
CORRADE_COMPARE(a.data()[3], -7.5f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4);
}
void DualComplexTest::isNormalized() {

15
src/Magnum/Math/Test/DualQuaternionTest.cpp

@ -322,13 +322,14 @@ void DualQuaternionTest::data() {
DualQuaternion a{{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}};
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr
#endif
Float d = *ca.data();
Float e = a.data()[7];
CORRADE_COMPARE(d, 1.0f);
CORRADE_COMPARE(e, 2.0f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[7], 2.0f);
CORRADE_COMPARE(ca.data()[4], 0.5f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 8);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 8);
}
void DualQuaternionTest::isNormalized() {

12
src/Magnum/Math/Test/DualTest.cpp

@ -208,10 +208,14 @@ void DualTest::data() {
a.dual() = -3.5f;
CORRADE_COMPARE(a, (Dual{2.0f, -3.5f}));
constexpr Float b = *ca.data();
Float c = a.data()[1];
CORRADE_COMPARE(b, 1.5f);
CORRADE_COMPARE(c, -3.5f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(*ca.data(), 1.5f);
CORRADE_COMPARE(a.data()[1], -3.5f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 2);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 2);
}
void DualTest::compare() {

31
src/Magnum/Math/Test/FrustumTest.cpp

@ -310,31 +310,42 @@ void FrustumTest::convert() {
void FrustumTest::data() {
/* Using default-constructed to verify that the planes are in correct order */
constexpr Frustum a;
constexpr Frustum ca;
#if !defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5
constexpr
#endif
Vector4 right = a.cbegin()[1];
Vector4 right = ca.cbegin()[1];
CORRADE_COMPARE(right, (Vector4{-1.0f, 0.0f, 0.0f, 1.0f}));
constexpr Vector4 bottom = a[2];
constexpr Vector4 bottom = ca[2];
CORRADE_COMPARE(bottom, (Vector4{0.0f, 1.0f, 0.0f, 1.0f}));
constexpr Vector4 near = a.near();
constexpr Vector4 near = ca.near();
CORRADE_COMPARE(near, (Vector4{0.0f, 0.0f, 1.0f, 1.0f}));
#if !defined(CORRADE_MSVC2015_COMPATIBILITY) && (!defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5)
constexpr
#endif
Vector4 far = *(a.cend() - 1);
Vector4 far = *(ca.cend() - 1);
CORRADE_COMPARE(far, (Vector4{0.0f, 0.0f, -1.0f, 1.0f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
Float b = *a.data();
CORRADE_COMPARE(b, 1.0f);
constexpr Frustum a{
{-1.0f, 2.0f, -3.0f, 0.1f},
{ 1.0f, -2.0f, 3.0f, 0.2f},
{-4.0f, 5.0f, -6.0f, 0.3f},
{ 4.0f, -5.0f, 6.0f, 0.4f},
{-7.0f, 8.0f, -9.0f, 0.5f},
{ 7.0f, 8.0f, 9.0f, 0.6f}};
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[9], 5.0f);
CORRADE_COMPARE(ca.data()[4], -1.0f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 24);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 24);
}
void FrustumTest::dataOutOfRange() {

15
src/Magnum/Math/Test/QuaternionTest.cpp

@ -334,13 +334,14 @@ void QuaternionTest::data() {
a.scalar() = 1.1f;
CORRADE_COMPARE(a, (Quaternion{{1.0f, 4.3f, 3.0f}, 1.1f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr
#endif
Float b = *ca.data();
Float c = a.data()[3];
CORRADE_COMPARE(b, 1.0f);
CORRADE_COMPARE(c, 1.1f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[3], 1.1f);
CORRADE_COMPARE(ca.data()[1], 2.0f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4);
}
void QuaternionTest::compare() {

45
src/Magnum/Math/Test/RangeTest.cpp

@ -111,6 +111,7 @@ struct RangeTest: Corrade::TestSuite::Tester {
void constructCopy();
void convert();
void data();
void access();
void compare();
void dimensionSlice();
@ -167,6 +168,7 @@ RangeTest::RangeTest() {
&RangeTest::constructCopy,
&RangeTest::convert,
&RangeTest::data,
&RangeTest::access,
&RangeTest::compare,
&RangeTest::dimensionSlice,
@ -425,7 +427,7 @@ void RangeTest::convert() {
CORRADE_VERIFY(!std::is_convertible<Range3D, Box>::value);
}
void RangeTest::access() {
void RangeTest::data() {
Range1Di line(34, 47);
Range2Di rect({34, 23}, {47, 30});
Range3Di cube({34, 23, -17}, {47, 30, 12});
@ -434,21 +436,32 @@ void RangeTest::access() {
constexpr Range2Di crect({34, 23}, {47, 30});
constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12});
CORRADE_COMPARE(line.data(), static_cast<void*>(&line));
CORRADE_COMPARE(rect.data(), static_cast<void*>(&rect));
CORRADE_COMPARE(cube.data(), static_cast<void*>(&cube));
constexpr Int lineData = *cline.data();
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr
#endif
Int rectData = *crect.data();
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr
#endif
Int cubeData = *ccube.data();
CORRADE_COMPARE(lineData, 34);
CORRADE_COMPARE(rectData, 34);
CORRADE_COMPARE(cubeData, 34);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(line.data()[1], 47);
CORRADE_COMPARE(cline.data()[1], 47);
CORRADE_COMPARE(*rect.data(), 34);
CORRADE_COMPARE(*crect.data(), 34);
CORRADE_COMPARE(cube.data()[2], -17);
CORRADE_COMPARE(ccube.data()[2], -17);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(line.data()), 2);
CORRADE_COMPARE(Corrade::Containers::arraySize(cline.data()), 2);
CORRADE_COMPARE(Corrade::Containers::arraySize(rect.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(crect.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(cube.data()), 6);
CORRADE_COMPARE(Corrade::Containers::arraySize(ccube.data()), 6);
}
void RangeTest::access() {
Range1Di line(34, 47);
Range2Di rect({34, 23}, {47, 30});
Range3Di cube({34, 23, -17}, {47, 30, 12});
constexpr Range1Di cline(34, 47);
constexpr Range2Di crect({34, 23}, {47, 30});
constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12});
CORRADE_COMPARE(line.min(), 34);
CORRADE_COMPARE(cline.min(), 34);

41
src/Magnum/Math/Test/RectangularMatrixTest.cpp

@ -402,37 +402,40 @@ void RectangularMatrixTest::convert() {
}
void RectangularMatrixTest::data() {
Matrix3x4 m;
Matrix3x4 a;
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f);
m[2] = vector;
m[1][1] = 1.0f;
m[0][2] = 1.5f;
a[2] = vector;
a[1][1] = 1.0f;
a[0][2] = 1.5f;
CORRADE_COMPARE(m[1][1], 1.0f);
CORRADE_COMPARE(m[0][2], 1.5f);
CORRADE_COMPARE(m[2], vector);
CORRADE_COMPARE(a[1][1], 1.0f);
CORRADE_COMPARE(a[0][2], 1.5f);
CORRADE_COMPARE(a[2], vector);
CORRADE_COMPARE(m, Matrix3x4(Vector4(0.0f, 0.0f, 1.5f, 0.0f),
CORRADE_COMPARE(a, Matrix3x4(Vector4(0.0f, 0.0f, 1.5f, 0.0f),
Vector4(0.0f, 1.0f, 0.0f, 0.0f),
Vector4(4.0f, 5.0f, 6.0f, 7.0f)));
/* Pointer chasings, i.e. *(b.data()[1]), are not possible */
constexpr Matrix3x4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.5f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.7f, 8.0f, 0.0f));
constexpr Matrix3x4 ca(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.5f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.7f, 8.0f, 0.0f));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */
constexpr
#endif
Vector4 b = a[2];
constexpr Float c = a[1][2];
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
Float d = *a.data();
Vector4 b = ca[2];
constexpr Float c = ca[1][2];
CORRADE_COMPARE(b, Vector4(7.0f, -1.7f, 8.0f, 0.0f));
CORRADE_COMPARE(c, 7.0f);
CORRADE_COMPARE(d, 3.0f);
/* Not constexpr anymore, as it has to reinterpret to return a
correctly-sized array */
CORRADE_COMPARE(a.data()[8], 4.0f);
CORRADE_COMPARE(ca.data()[1], 5.0f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 12);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 12);
}
void RectangularMatrixTest::row() {

26
src/Magnum/Math/Test/VectorTest.cpp

@ -341,23 +341,29 @@ void VectorTest::isNormalized() {
}
void VectorTest::data() {
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f);
vector[2] = 1.0f;
vector[3] = 1.5f;
Vector4 a(4.0f, 5.0f, 6.0f, 7.0f);
a[2] = 1.0f;
a[3] = 1.5f;
CORRADE_COMPARE(vector[2], 1.0f);
CORRADE_COMPARE(vector[3], 1.5f);
CORRADE_COMPARE(vector, Vector4(4.0f, 5.0f, 1.0f, 1.5f));
CORRADE_COMPARE(a[2], 1.0f);
CORRADE_COMPARE(a[3], 1.5f);
CORRADE_COMPARE(a, Vector4(4.0f, 5.0f, 1.0f, 1.5f));
constexpr Vector4 ca(1.0f, 2.0f, -3.0f, 4.5f);
constexpr Float f = ca[3];
CORRADE_COMPARE(f, 4.5f);
/* Pointer chasings, i.e. *(b.data()[3]), are not possible */
constexpr Vector4 a(1.0f, 2.0f, -3.0f, 4.5f);
constexpr Float f = a[3];
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr
#endif
Float g = *a.data();
CORRADE_COMPARE(f, 4.5f);
Float g = *ca.data();
CORRADE_COMPARE(a.data()[1], 5.0f);
CORRADE_COMPARE(g, 1.0f);
/* It actually returns an array */
CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4);
}
void VectorTest::compare() {

15
src/Magnum/Math/Vector.h

@ -233,12 +233,21 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Raw data
* @return One-dimensional array of `size` length.
*
* Contrary to what Doxygen shows, returns reference to an
* one-dimensional fixed-size array of `size` elements, i.e.
* @cpp T(&)[size] @ce.
* @see @ref operator[]()
* @todoc Fix once there's a possibility to patch the signature in a
* post-processing step (https://github.com/mosra/m.css/issues/56)
*/
T* data() { return _data; }
constexpr const T* data() const { return _data; } /**< @overload */
#ifdef DOXYGEN_GENERATING_OUTPUT
T* data();
constexpr const T* data() const; /**< @overload */
#else
auto data() -> T(&)[size] { return _data; }
constexpr auto data() const -> const T(&)[size] { return _data; }
#endif
/**
* @brief Value at given position

Loading…
Cancel
Save