diff --git a/doc/changelog.dox b/doc/changelog.dox index 515adb460..8243c862d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -121,6 +121,10 @@ See also: - Ability to use @ref Math::Complex, @ref Math::DualComplex, @ref Math::Quaternion, @ref Math::DualQuaternion with @ref Corrade::Utility::Configuration and @ref Corrade::Utility::Arguments +- Added @ref Math::Complex::data(), @ref Math::Quaternion::data(), + @ref Math::DualComplex::data(), @ref Math::DualQuaternion::data(), + @ref Math::Bezier::data() and @ref Math::CubicHermite::data() for simple + access to underlying memory like with other math types - New @ref Math::min(), @ref Math::max() and @ref Math::minmax() overloads taking plain C arrays diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h index 3909332c3..1eee72bca 100644 --- a/src/Magnum/Math/Bezier.h +++ b/src/Magnum/Math/Bezier.h @@ -140,6 +140,15 @@ template class Bezier { return Implementation::BezierConverter::to(*this); } + /** + * @brief Raw data + * @return One-dimensional array of @cpp order + 1 @ce elements + * + * @see @ref operator[]() + */ + Vector* data() { return _data; } + constexpr const Vector* data() const { return _data; } /**< @overload */ + /** @brief Equality comparison */ bool operator==(const Bezier& other) const { for(std::size_t i = 0; i != order + 1; ++i) diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index 7af206749..754f50de6 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -172,6 +172,15 @@ template class Complex { return Implementation::ComplexConverter::to(*this); } + /** + * @brief Raw data + * @return One-dimensional array of two elements + * + * @see @ref real(), @ref imaginary() + */ + T* data() { return &_real; } + constexpr const T* data() const { return &_real; } /**< @overload */ + /** @brief Equality comparison */ bool operator==(const Complex& other) const { return TypeTraits::equals(_real, other._real) && @@ -195,11 +204,19 @@ template class Complex { return Implementation::isNormalizedSquared(dot()); } - /** @brief Real part (@f$ a_0 @f$) */ + /** + * @brief Real part (@f$ a_0 @f$) + * + * @see @ref data() + */ T& real() { return _real; } constexpr T real() const { return _real; } /**< @overload */ - /** @brief Imaginary part (@f$ a_i @f$) */ + /** + * @brief Imaginary part (@f$ a_i @f$) + * + * @see @ref data() + */ T& imaginary() { return _imaginary; } constexpr T imaginary() const { return _imaginary; } /**< @overload */ diff --git a/src/Magnum/Math/CubicHermite.h b/src/Magnum/Math/CubicHermite.h index cd088bad9..c1c93a1a7 100644 --- a/src/Magnum/Math/CubicHermite.h +++ b/src/Magnum/Math/CubicHermite.h @@ -144,6 +144,15 @@ template class CubicHermite { */ template constexpr explicit CubicHermite(const CubicHermite& other) noexcept: _inTangent{T(other._inTangent)}, _point{T(other._point)}, _outTangent{T(other._outTangent)} {} + /** + * @brief Raw data + * @return One-dimensional array of three elements + * + * @see @ref inTangent(), @ref point(), @ref outTangent() + */ + T* data() { return &_inTangent; } + constexpr const T* data() const { return &_inTangent; } /**< @overload */ + /** @brief Equality comparison */ bool operator==(const CubicHermite& other) const; diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index 2e74a3230..fd4a3a9dd 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -115,6 +115,15 @@ template class Dual { /** @brief Copy constructor */ constexpr /*implicit*/ Dual(const Dual&) noexcept = default; + /** + * @brief Raw data + * @return One-dimensional array of two elements + * + * @see @ref real(), @ref dual() + */ + T* data() { return &_real; } + constexpr const T* data() const { return &_real; } /**< @overload */ + /** @brief Equality comparison */ bool operator==(const Dual& other) const { return TypeTraits::equals(_real, other._real) && @@ -126,13 +135,21 @@ template class Dual { return !operator==(other); } - /** @brief Real part (@f$ a_0 @f$) */ + /** + * @brief Real part (@f$ a_0 @f$) + * + * @see @ref data() + */ T& real() { return _real; } /* Returning const so it's possible to call constexpr functions on the result. WTF, C++?! */ constexpr const T real() const { return _real; } /**< @overload */ - /** @brief Dual part (@f$ a_\epsilon @f$) */ + /** + * @brief Dual part (@f$ a_\epsilon @f$) + * + * @see @ref data() + */ T& dual() { return _dual; } /* Returning const so it's possible to call constexpr functions on the result. WTF, C++?! */ diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index 58571fa6d..298c51f68 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -180,6 +180,15 @@ template class DualComplex: public Dual> { return Implementation::DualComplexConverter::to(*this); } + /** + * @brief Raw data + * @return One-dimensional array of four elements + * + * @see @ref real(), @ref dual() + */ + T* data() { return Dual>::data()->data(); } + constexpr const T* data() const { return Dual>::data()->data(); } /**< @overload */ + /** * @brief Whether the dual complex number is normalized * diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index b268c9a26..7c30ed0c3 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -329,6 +329,15 @@ template class DualQuaternion: public Dual> { return Implementation::DualQuaternionConverter::to(*this); } + /** + * @brief Raw data + * @return One-dimensional array of eight elements + * + * @see @ref real(), @ref dual() + */ + T* data() { return Dual>::data()->data(); } + constexpr const T* data() const { return Dual>::data()->data(); } /**< @overload */ + /** * @brief Whether the dual quaternion is normalized * diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 8a29f65f0..45944db51 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -318,6 +318,15 @@ template class Quaternion { return Implementation::QuaternionConverter::to(*this); } + /** + * @brief Raw data + * @return One-dimensional array of four elements + * + * @see @ref vector(), @ref scalar() + */ + T* data() { return _vector.data(); } + constexpr const T* data() const { return _vector.data(); } /**< @overload */ + /** @brief Equality comparison */ bool operator==(const Quaternion& other) const { return _vector == other._vector && TypeTraits::equals(_scalar, other._scalar); diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index 6bc198d08..dd7a4261e 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -221,6 +221,11 @@ void BezierTest::data() { #endif Vector2 c = b[2]; CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f})); + + constexpr Vector2 d = *b.data(); + Vector2 e = a.data()[2]; + CORRADE_COMPARE(d, (Vector2{3.5f, 0.1f})); + CORRADE_COMPARE(e, (Vector2{0.7f, 20.3f})); } void BezierTest::compare() { diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index fd9c100a0..88aaa3cdb 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -267,6 +267,11 @@ void ComplexTest::data() { a.real() = 2.0f; 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); } void ComplexTest::compare() { diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index 0555f115d..619b22639 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -600,8 +600,13 @@ void CubicHermiteTest::dataScalar() { CubicHermite1D a{2.0f, -2.0f, -0.5f}; a.inTangent() = 3.0f; a.point() = 1.0f; - a.outTangent() = 2.0f; - CORRADE_COMPARE(a, (CubicHermite1D{3.0f, 1.0f, 2.0f})); + 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); } void CubicHermiteTest::dataVector() { @@ -618,6 +623,11 @@ void CubicHermiteTest::dataVector() { a.point().x() = 1.0f; 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})); } void CubicHermiteTest::dataComplex() { @@ -634,6 +644,11 @@ void CubicHermiteTest::dataComplex() { a.point().real() = 1.0f; 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})); } void CubicHermiteTest::dataQuaternion() { @@ -660,6 +675,11 @@ void CubicHermiteTest::dataQuaternion() { {{1.0f, 3.0f, -1.0f}, 3.0f}, {{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})); } void CubicHermiteTest::compareScalar() { diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 7637520aa..49a44feac 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -64,6 +64,8 @@ struct DualComplexTest: Corrade::TestSuite::Tester { void constructCopy(); void convert(); + void data(); + void isNormalized(); template void isNormalizedEpsilonRotation(); template void isNormalizedEpsilonTranslation(); @@ -109,6 +111,8 @@ DualComplexTest::DualComplexTest() { &DualComplexTest::constructCopy, &DualComplexTest::convert, + &DualComplexTest::data, + &DualComplexTest::isNormalized, &DualComplexTest::isNormalizedEpsilonRotation, &DualComplexTest::isNormalizedEpsilonRotation, @@ -144,14 +148,11 @@ DualComplexTest::DualComplexTest() { void DualComplexTest::construct() { constexpr DualComplex a = {{-1.0f, 2.5f}, {3.0f, -7.5f}}; CORRADE_COMPARE(a, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + CORRADE_COMPARE(a.real(), Complex(-1.0f, 2.5f)); + CORRADE_COMPARE(a.dual(), Complex(3.0f, -7.5f)); - constexpr Complex b = a.real(); - constexpr Complex c = a.dual(); - CORRADE_COMPARE(b, Complex(-1.0f, 2.5f)); - CORRADE_COMPARE(c, Complex(3.0f, -7.5f)); - - constexpr DualComplex d(Complex(-1.0f, 2.5f)); - CORRADE_COMPARE(d, DualComplex({-1.0f, 2.5f}, {0.0f, 0.0f})); + constexpr DualComplex b(Complex(-1.0f, 2.5f)); + CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {0.0f, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); } @@ -247,6 +248,22 @@ void DualComplexTest::convert() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void DualComplexTest::data() { + constexpr DualComplex ca{{-1.0f, 2.5f}, {3.0f, -7.5f}}; + + constexpr Complex b = ca.real(); + constexpr Complex c = ca.dual(); + CORRADE_COMPARE(b, Complex(-1.0f, 2.5f)); + CORRADE_COMPARE(c, Complex(3.0f, -7.5f)); + + 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); +} + void DualComplexTest::isNormalized() { CORRADE_VERIFY(!DualComplex({2.0f, 1.0f}, {}).isNormalized()); CORRADE_VERIFY((DualComplex::rotation(Deg(23.0f))*DualComplex::translation({6.0f, 3.0f})).isNormalized()); diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 23875683d..cac529bd6 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -67,6 +67,8 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester { void constructCopy(); void convert(); + void data(); + void isNormalized(); template void isNormalizedEpsilonRotation(); template void isNormalizedEpsilonTranslation(); @@ -117,6 +119,8 @@ DualQuaternionTest::DualQuaternionTest() { &DualQuaternionTest::constructCopy, &DualQuaternionTest::convert, + &DualQuaternionTest::data, + &DualQuaternionTest::isNormalized, &DualQuaternionTest::isNormalizedEpsilonRotation, &DualQuaternionTest::isNormalizedEpsilonRotation, @@ -154,15 +158,11 @@ DualQuaternionTest::DualQuaternionTest() { void DualQuaternionTest::construct() { constexpr DualQuaternion a = {{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}}; CORRADE_COMPARE(a, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f})); + CORRADE_COMPARE(a.real(), Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); + CORRADE_COMPARE(a.dual(), Quaternion({0.5f, -3.1f, 3.3f}, 2.0f)); - constexpr Quaternion b = a.real(); - CORRADE_COMPARE(b, Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); - - constexpr Quaternion c = a.dual(); - CORRADE_COMPARE(c, Quaternion({0.5f, -3.1f, 3.3f}, 2.0f)); - - constexpr DualQuaternion d({{1.0f, 2.0f, 3.0f}, -4.0f}); - CORRADE_COMPARE(d, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); + constexpr DualQuaternion b({{1.0f, 2.0f, 3.0f}, -4.0f}); + CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); } @@ -275,6 +275,23 @@ void DualQuaternionTest::convert() { CORRADE_VERIFY(!(std::is_convertible::value)); } +void DualQuaternionTest::data() { + constexpr DualQuaternion ca{{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}}; + + constexpr Quaternion b = ca.real(); + CORRADE_COMPARE(b, Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); + + constexpr Quaternion c = ca.dual(); + CORRADE_COMPARE(c, Quaternion({0.5f, -3.1f, 3.3f}, 2.0f)); + + DualQuaternion a{{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}}; + + constexpr Float d = *ca.data(); + Float e = a.data()[7]; + CORRADE_COMPARE(d, 1.0f); + CORRADE_COMPARE(e, 2.0f); +} + void DualQuaternionTest::isNormalized() { CORRADE_VERIFY(!DualQuaternion({{1.0f, 2.0f, 3.0f}, 4.0f}, {}).isNormalized()); CORRADE_VERIFY((DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({0.9f, -1.0f, -0.5f})).isNormalized()); diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index f53a42981..557d3d157 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -189,6 +189,11 @@ void DualTest::data() { a.real() = 2.0f; 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); } void DualTest::compare() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index bdf9cbb71..390c0977e 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -283,6 +283,11 @@ void QuaternionTest::data() { a.vector().y() = 4.3f; a.scalar() = 1.1f; CORRADE_COMPARE(a, (Quaternion{{1.0f, 4.3f, 3.0f}, 1.1f})); + + constexpr Float b = *ca.data(); + Float c = a.data()[3]; + CORRADE_COMPARE(b, 1.0f); + CORRADE_COMPARE(c, 1.1f); } void QuaternionTest::compare() {