| Message ID | 20260914123833.2724712-2-laurent.pinchart@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
2026. 09. 14. 14:38 keltezéssel, Laurent Pinchart írta: > The Matrix class has a member function to invert a matrix, but no > function to transpose it. We already have one open-coded transpose > operation in the software ISP implementation, and more would likely be > added. Add a transpose() member function to the Matrix class to cover > this need. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > Changes since v2: > > - Inline the implementation > - Add a function template argument to support optional type conversion > - Use int and unsigned int in the unit test > > Changes since v1: > > - Add and use nonc-const data() > - Add unit test > --- Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > include/libcamera/internal/matrix.h | 19 +++++++++++++++++++ > src/libcamera/matrix.cpp | 20 +++++++++++++++++++- > test/matrix.cpp | 9 +++++++++ > 3 files changed, 47 insertions(+), 1 deletion(-) > > diff --git a/include/libcamera/internal/matrix.h b/include/libcamera/internal/matrix.h > index f74cda103c72..45ce0000a4cf 100644 > --- a/include/libcamera/internal/matrix.h > +++ b/include/libcamera/internal/matrix.h > @@ -76,6 +76,8 @@ public: > > constexpr std::span<const T, Rows * Cols> data() const { return data_; } > > + constexpr std::span<T, Rows * Cols> data() { return data_; } > + > constexpr std::span<const T, Cols> operator[](size_t i) const > { > return std::span<const T, Cols>{ &data_.data()[i * Cols], Cols }; > @@ -115,6 +117,23 @@ public: > return inverse; > } > > + template<typename U = T> > + [[nodiscard]] > + constexpr Matrix<U, Cols, Rows> transpose() const > + { > + static_assert(std::is_convertible_v<T, U>); > + > + Matrix<U, Cols, Rows> transposed; > + std::span<U, Rows * Cols> data = transposed.data(); > + > + for (unsigned int r = 0; r < Rows; ++r) { > + for (unsigned int c = 0; c < Cols; ++c) > + data[c * Rows + r] = data_[r * Cols + c]; > + } > + > + return transposed; > + } > + > private: > /* > * \todo The initializer is only necessary for the constructor to be > diff --git a/src/libcamera/matrix.cpp b/src/libcamera/matrix.cpp > index 9cb0885b3b54..cbaaaa9634e8 100644 > --- a/src/libcamera/matrix.cpp > +++ b/src/libcamera/matrix.cpp > @@ -69,7 +69,7 @@ LOG_DEFINE_CATEGORY(Matrix) > */ > > /** > - * \fn Matrix::data() > + * \fn Matrix::data() const > * \brief Access the matrix data as a linear array > * > * Access the contents of the matrix as a one-dimensional linear array of > @@ -79,6 +79,11 @@ LOG_DEFINE_CATEGORY(Matrix) > * \return A span referencing the matrix data as a linear array > */ > > +/** > + * \fn Matrix::data() > + * \copydoc Matrix::data() const > + */ > + > /** > * \fn std::span<const T, Cols> Matrix::operator[](size_t i) const > * \brief Index to a row in the matrix > @@ -107,6 +112,19 @@ LOG_DEFINE_CATEGORY(Matrix) > * \return The inverse of the matrix > */ > > +/** > + * \fn Matrix::transpose() const > + * \brief Compute the transpose of the matrix > + * \tparam U Type of the numerical values in the tranposed matrix > + * > + * This function computes the transpose of the matrix. The optional template > + * parameter \a U specifies the type of the numerical values in the result. It > + * defaults to \a T, and can be specified manually to convert to a different > + * data type while transposing. > + * > + * \return The transpose of the matrix > + */ > + > /** > * \fn Matrix::operator[](size_t i) > * \copydoc Matrix::operator[](size_t i) const > diff --git a/test/matrix.cpp b/test/matrix.cpp > index 4afae2da7866..9c69554bd1ee 100644 > --- a/test/matrix.cpp > +++ b/test/matrix.cpp > @@ -46,6 +46,15 @@ protected: > ASSERT_EQ(m5[1][0], 0.0); > ASSERT_EQ(m5[1][1], 1.0); > > + Matrix<int, 2, 3> m6({ 1, 2, 3, 4, 5, 6 }); > + Matrix<unsigned int, 3, 2> m7 = m6.transpose<unsigned int>(); > + ASSERT_EQ(m7[0][0], 1); > + ASSERT_EQ(m7[0][1], 4); > + ASSERT_EQ(m7[1][0], 2); > + ASSERT_EQ(m7[1][1], 5); > + ASSERT_EQ(m7[2][0], 3); > + ASSERT_EQ(m7[2][1], 6); > + > return TestPass; > } > };
diff --git a/include/libcamera/internal/matrix.h b/include/libcamera/internal/matrix.h index f74cda103c72..45ce0000a4cf 100644 --- a/include/libcamera/internal/matrix.h +++ b/include/libcamera/internal/matrix.h @@ -76,6 +76,8 @@ public: constexpr std::span<const T, Rows * Cols> data() const { return data_; } + constexpr std::span<T, Rows * Cols> data() { return data_; } + constexpr std::span<const T, Cols> operator[](size_t i) const { return std::span<const T, Cols>{ &data_.data()[i * Cols], Cols }; @@ -115,6 +117,23 @@ public: return inverse; } + template<typename U = T> + [[nodiscard]] + constexpr Matrix<U, Cols, Rows> transpose() const + { + static_assert(std::is_convertible_v<T, U>); + + Matrix<U, Cols, Rows> transposed; + std::span<U, Rows * Cols> data = transposed.data(); + + for (unsigned int r = 0; r < Rows; ++r) { + for (unsigned int c = 0; c < Cols; ++c) + data[c * Rows + r] = data_[r * Cols + c]; + } + + return transposed; + } + private: /* * \todo The initializer is only necessary for the constructor to be diff --git a/src/libcamera/matrix.cpp b/src/libcamera/matrix.cpp index 9cb0885b3b54..cbaaaa9634e8 100644 --- a/src/libcamera/matrix.cpp +++ b/src/libcamera/matrix.cpp @@ -69,7 +69,7 @@ LOG_DEFINE_CATEGORY(Matrix) */ /** - * \fn Matrix::data() + * \fn Matrix::data() const * \brief Access the matrix data as a linear array * * Access the contents of the matrix as a one-dimensional linear array of @@ -79,6 +79,11 @@ LOG_DEFINE_CATEGORY(Matrix) * \return A span referencing the matrix data as a linear array */ +/** + * \fn Matrix::data() + * \copydoc Matrix::data() const + */ + /** * \fn std::span<const T, Cols> Matrix::operator[](size_t i) const * \brief Index to a row in the matrix @@ -107,6 +112,19 @@ LOG_DEFINE_CATEGORY(Matrix) * \return The inverse of the matrix */ +/** + * \fn Matrix::transpose() const + * \brief Compute the transpose of the matrix + * \tparam U Type of the numerical values in the tranposed matrix + * + * This function computes the transpose of the matrix. The optional template + * parameter \a U specifies the type of the numerical values in the result. It + * defaults to \a T, and can be specified manually to convert to a different + * data type while transposing. + * + * \return The transpose of the matrix + */ + /** * \fn Matrix::operator[](size_t i) * \copydoc Matrix::operator[](size_t i) const diff --git a/test/matrix.cpp b/test/matrix.cpp index 4afae2da7866..9c69554bd1ee 100644 --- a/test/matrix.cpp +++ b/test/matrix.cpp @@ -46,6 +46,15 @@ protected: ASSERT_EQ(m5[1][0], 0.0); ASSERT_EQ(m5[1][1], 1.0); + Matrix<int, 2, 3> m6({ 1, 2, 3, 4, 5, 6 }); + Matrix<unsigned int, 3, 2> m7 = m6.transpose<unsigned int>(); + ASSERT_EQ(m7[0][0], 1); + ASSERT_EQ(m7[0][1], 4); + ASSERT_EQ(m7[1][0], 2); + ASSERT_EQ(m7[1][1], 5); + ASSERT_EQ(m7[2][0], 3); + ASSERT_EQ(m7[2][1], 6); + return TestPass; } };
The Matrix class has a member function to invert a matrix, but no function to transpose it. We already have one open-coded transpose operation in the software ISP implementation, and more would likely be added. Add a transpose() member function to the Matrix class to cover this need. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- Changes since v2: - Inline the implementation - Add a function template argument to support optional type conversion - Use int and unsigned int in the unit test Changes since v1: - Add and use nonc-const data() - Add unit test --- include/libcamera/internal/matrix.h | 19 +++++++++++++++++++ src/libcamera/matrix.cpp | 20 +++++++++++++++++++- test/matrix.cpp | 9 +++++++++ 3 files changed, 47 insertions(+), 1 deletion(-)