From 23fcc1c6c9726ef212701971103b18cd1936ae9b Mon Sep 17 00:00:00 2001 From: Blake Date: Mon, 9 Feb 2026 21:12:03 -0500 Subject: [PATCH] MatrixBase::diagonalView issue 604 libeigen/eigen!2126 Closes #604 --- Eigen/src/Core/DiagonalMatrix.h | 47 ++++++++++++++++++++ Eigen/src/Core/MatrixBase.h | 11 +++++ doc/snippets/MatrixBase_diagonalView.cpp | 5 +++ test/CMakeLists.txt | 1 + test/diagonalview.cpp | 55 ++++++++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 doc/snippets/MatrixBase_diagonalView.cpp create mode 100644 test/diagonalview.cpp diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 52630d929..3b099ff52 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -372,6 +372,53 @@ bool MatrixBase::isDiagonal(const RealScalar& prec) const { return true; } +/** \returns DiagonalWrapper. + * + * Example: \include MatrixBase_diagonalView.cpp + * Output: \verbinclude MatrixBase_diagonalView.out + * + * \sa diagonalView() + */ + +/** This is the non-const version of diagonalView() with DiagIndex_ . */ +template +template +EIGEN_DEVICE_FUNC DiagonalWrapper> MatrixBase::diagonalView() { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived()); + return ReturnType(diag); +} + +/** This is the const version of diagonalView() with DiagIndex_ . */ +template +template +EIGEN_DEVICE_FUNC DiagonalWrapper> MatrixBase::diagonalView() const { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived()); + return ReturnType(diag); +} + +/** This is the non-const version of diagonalView() with dynamic index. */ +template +EIGEN_DEVICE_FUNC DiagonalWrapper> MatrixBase::diagonalView(Index index) { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived(), index); + return ReturnType(diag); +} + +/** This is the const version of diagonalView() with dynamic index. */ +template +EIGEN_DEVICE_FUNC DiagonalWrapper> MatrixBase::diagonalView( + Index index) const { + typedef Diagonal DiagType; + typedef DiagonalWrapper ReturnType; + DiagType diag(this->derived(), index); + return ReturnType(diag); +} + namespace internal { template <> diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 045993d46..f12b93fea 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -274,6 +274,17 @@ class MatrixBase : public DenseBase { const RealScalar& prec = NumTraits::dummy_precision()) const; bool isUnitary(const RealScalar& prec = NumTraits::dummy_precision()) const; + /* diagonalView */ + template + EIGEN_DEVICE_FUNC DiagonalWrapper> diagonalView(); + + template + EIGEN_DEVICE_FUNC DiagonalWrapper> diagonalView() const; + + EIGEN_DEVICE_FUNC DiagonalWrapper> diagonalView(Index index); + + EIGEN_DEVICE_FUNC DiagonalWrapper> diagonalView(Index index) const; + /** \returns true if each coefficients of \c *this and \a other are all exactly equal. * \warning When using floating point scalar values you probably should rather use a * fuzzy comparison such as isApprox() diff --git a/doc/snippets/MatrixBase_diagonalView.cpp b/doc/snippets/MatrixBase_diagonalView.cpp new file mode 100644 index 000000000..1b2ca5966 --- /dev/null +++ b/doc/snippets/MatrixBase_diagonalView.cpp @@ -0,0 +1,5 @@ +Matrix3d mat3; +mat3 << 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9; +cout << "Here's the matrix m:" << endl << m << endl; +cout << "m.diagonal().asDiagonal() returns: " << m.diagonal().asDiagonal() << endl; +cout << "m.diagonalView() returns: " << m.diagonalView() << endl; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f704c4aa0..dc5f958f1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -211,6 +211,7 @@ ei_add_test(product_small) ei_add_test(product_large) ei_add_test(product_extra) ei_add_test(diagonalmatrices) +ei_add_test(diagonalview) ei_add_test(skew_symmetric_matrix3) ei_add_test(adjoint) ei_add_test(diagonal) diff --git a/test/diagonalview.cpp b/test/diagonalview.cpp new file mode 100644 index 000000000..0d83c8e3b --- /dev/null +++ b/test/diagonalview.cpp @@ -0,0 +1,55 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Benoit Jacob +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// discard stack allocation as that too bypasses malloc +#define EIGEN_STACK_ALLOCATION_LIMIT 0 +// heap allocation will raise an assert if enabled at runtime +#define EIGEN_RUNTIME_NO_MALLOC + +#include "main.h" +using namespace std; +template +void diagonalview(const MatrixType& m) { + enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime }; + Index rows = m.rows(); + Index cols = m.cols(); + // create random matrix + MatrixType m1 = MatrixType::Random(rows, cols); + + // check equivalence to diagonal(i).asDiagonal() for dynamic indexes + VERIFY_IS_APPROX(m1.diagonal(0).asDiagonal().toDenseMatrix(), m1.diagonalView(0).toDenseMatrix()); + // subdiagonal + VERIFY_IS_APPROX(m1.diagonal(-1).asDiagonal().toDenseMatrix(), m1.diagonalView(-1).toDenseMatrix()); + // superdiagonal + VERIFY_IS_APPROX(m1.diagonal(1).asDiagonal().toDenseMatrix(), m1.diagonalView(1).toDenseMatrix()); + + // check equivalence to diagonal(i).asDiagonal() for compile time indexes + VERIFY_IS_APPROX(m1.diagonal(0).asDiagonal().toDenseMatrix(), m1.template diagonalView<0>().toDenseMatrix()); + // sub + VERIFY_IS_APPROX(m1.diagonal(-1).asDiagonal().toDenseMatrix(), m1.template diagonalView<-1>().toDenseMatrix()); + // super + VERIFY_IS_APPROX(m1.diagonal(1).asDiagonal().toDenseMatrix(), m1.template diagonalView<1>().toDenseMatrix()); + + // check const overloads + const auto m2(m1); + typedef decltype(m1) Type1; + typedef decltype(m2) Type2; + constexpr bool types_are_same = std::is_same::value; + VERIFY(!types_are_same); + + VERIFY_IS_APPROX(m2.diagonal(0).asDiagonal().toDenseMatrix(), m2.diagonalView(0).toDenseMatrix()); + VERIFY_IS_APPROX(m2.diagonal(1).asDiagonal().toDenseMatrix(), m2.template diagonalView<1>().toDenseMatrix()); +} + +EIGEN_DECLARE_TEST(diagonalview) { + for (int i = 0; i < g_repeat; i++) { + CALL_SUBTEST_1(diagonalview(Matrix())); + CALL_SUBTEST_2(diagonalview(Matrix())); + } +}