libcamera v0.7.2+rpt20261009
Supporting cameras in Linux since 2019
Loading...
Searching...
No Matches
matrix.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
4 *
5 * Matrix and related operations
6 */
7#pragma once
8
9#include <algorithm>
10#include <span>
11#include <sstream>
12#include <type_traits>
13#include <vector>
14
15#include <libcamera/base/log.h>
16
18
19namespace libcamera {
20
22
23#ifndef __DOXYGEN__
24template<typename T>
25bool matrixInvert(std::span<const T> dataIn, std::span<T> dataOut, unsigned int dim,
26 std::span<T> scratchBuffer, std::span<unsigned int> swapBuffer);
27#endif /* __DOXYGEN__ */
28
29template<typename T, unsigned int Rows, unsigned int Cols>
30class Matrix
31{
32 static_assert(std::is_arithmetic_v<T>, "Matrix type must be arithmetic");
33
34public:
35 constexpr Matrix()
36 {
37 }
38
39 Matrix(const std::array<T, Rows * Cols> &data)
40 {
41 std::copy(data.begin(), data.end(), data_.begin());
42 }
43
44 Matrix(std::span<const T, Rows * Cols> data)
45 {
46 std::copy(data.begin(), data.end(), data_.begin());
47 }
48
49 static constexpr Matrix identity()
50 {
51 Matrix ret;
52 for (size_t i = 0; i < std::min(Rows, Cols); i++)
53 ret[i][i] = static_cast<T>(1);
54 return ret;
55 }
56
57 ~Matrix() = default;
58
59 std::string toString() const
60 {
61 std::stringstream out;
62
63 out << "Matrix { ";
64 for (unsigned int i = 0; i < Rows; i++) {
65 out << "[ ";
66 for (unsigned int j = 0; j < Cols; j++) {
67 out << (*this)[i][j];
68 out << ((j + 1 < Cols) ? ", " : " ");
69 }
70 out << ((i + 1 < Rows) ? "], " : "]");
71 }
72 out << " }";
73
74 return out.str();
75 }
76
77 constexpr std::span<const T, Rows * Cols> data() const { return data_; }
78
79 constexpr std::span<T, Rows * Cols> data() { return data_; }
80
81 constexpr std::span<const T, Cols> operator[](size_t i) const
82 {
83 return std::span<const T, Cols>{ &data_.data()[i * Cols], Cols };
84 }
85
86 constexpr std::span<T, Cols> operator[](size_t i)
87 {
88 return std::span<T, Cols>{ &data_.data()[i * Cols], Cols };
89 }
90
91#ifndef __DOXYGEN__
92 template<typename U, std::enable_if_t<std::is_arithmetic_v<U>>>
93#else
94 template<typename U>
95#endif /* __DOXYGEN__ */
97 {
98 for (unsigned int i = 0; i < Rows * Cols; i++)
99 data_[i] *= d;
100 return *this;
101 }
102
103 Matrix<T, Rows, Cols> inverse(bool *ok = nullptr) const
104 {
105 static_assert(Rows == Cols, "Matrix must be square");
106
108 std::array<T, Rows * Cols * 2> scratchBuffer;
109 std::array<unsigned int, Rows> swapBuffer;
110 bool res = matrixInvert(std::span<const T>(data_),
111 std::span<T>(inverse.data_),
112 Rows,
113 std::span<T>(scratchBuffer),
114 std::span<unsigned int>(swapBuffer));
115 if (ok)
116 *ok = res;
117 return inverse;
118 }
119
120 template<typename U = T>
121 [[nodiscard]]
123 {
124 static_assert(std::is_convertible_v<T, U>);
125
126 Matrix<U, Cols, Rows> transposed;
127 std::span<U, Rows * Cols> data = transposed.data();
128
129 for (unsigned int r = 0; r < Rows; ++r) {
130 for (unsigned int c = 0; c < Cols; ++c)
131 data[c * Rows + r] = data_[r * Cols + c];
132 }
133
134 return transposed;
135 }
136
137private:
138 /*
139 * \todo The initializer is only necessary for the constructor to be
140 * constexpr in C++17. Remove the initializer as soon as we are on
141 * C++20.
142 */
143 std::array<T, Rows * Cols> data_ = {};
144};
145
146#ifndef __DOXYGEN__
147template<typename T, typename U, unsigned int Rows, unsigned int Cols,
148 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
149#else
150template<typename T, typename U, unsigned int Rows, unsigned int Cols>
151#endif /* __DOXYGEN__ */
153{
155
156 for (unsigned int i = 0; i < Rows; i++) {
157 for (unsigned int j = 0; j < Cols; j++)
158 result[i][j] = d * m[i][j];
159 }
160
161 return result;
162}
163
164#ifndef __DOXYGEN__
165template<typename T, typename U, unsigned int Rows, unsigned int Cols,
166 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
167#else
168template<typename T, typename U, unsigned int Rows, unsigned int Cols>
169#endif /* __DOXYGEN__ */
171{
172 return d * m;
173}
174
175template<typename T1, unsigned int R1, unsigned int C1, typename T2, unsigned int R2, unsigned int C2>
177 const Matrix<T2, R2, C2> &m2)
178{
179 static_assert(C1 == R2, "Matrix dimensions must match for multiplication");
180 Matrix<std::common_type_t<T1, T2>, R1, C2> result;
181
182 for (unsigned int i = 0; i < R1; i++) {
183 for (unsigned int j = 0; j < C2; j++) {
184 std::common_type_t<T1, T2> sum = 0;
185
186 for (unsigned int k = 0; k < C1; k++)
187 sum += m1[i][k] * m2[k][j];
188
189 result[i][j] = sum;
190 }
191 }
192
193 return result;
194}
195
196template<typename T, unsigned int Rows, unsigned int Cols>
198{
200
201 for (unsigned int i = 0; i < Rows; i++) {
202 for (unsigned int j = 0; j < Cols; j++)
203 result[i][j] = m1[i][j] + m2[i][j];
204 }
205
206 return result;
207}
208
209#ifndef __DOXYGEN__
210bool matrixValidateValueNode(const ValueNode &obj, unsigned int size);
211
212template<typename T, unsigned int Rows, unsigned int Cols>
213std::ostream &operator<<(std::ostream &out, const Matrix<T, Rows, Cols> &m)
214{
215 out << m.toString();
216 return out;
217}
218
219template<typename T, unsigned int Rows, unsigned int Cols>
220struct ValueNode::Accessor<Matrix<T, Rows, Cols>> {
221 std::optional<Matrix<T, Rows, Cols>> get(const ValueNode &obj) const
222 {
223 if (!matrixValidateValueNode(obj, Rows * Cols))
224 return std::nullopt;
225
226 Matrix<T, Rows, Cols> matrix;
227 T *data = &matrix[0][0];
228
229 unsigned int i = 0;
230 for (const ValueNode &entry : obj.asList()) {
231 const auto value = entry.get<T>();
232 if (!value)
233 return std::nullopt;
234
235 data[i++] = *value;
236 }
237
238 return matrix;
239 }
240};
241#endif /* __DOXYGEN__ */
242
243} /* namespace libcamera */
Matrix class.
Definition matrix.h:31
static constexpr Matrix identity()
Construct an identity matrix.
Definition matrix.h:49
Matrix(const std::array< T, Rows *Cols > &data)
Construct a matrix from supplied data.
Definition matrix.h:39
Matrix< T, Rows, Cols > & operator*=(U d)
Multiply the matrix by a scalar in-place.
Definition matrix.h:96
Matrix< T, Rows, Cols > inverse(bool *ok=nullptr) const
Compute the inverse of the matrix.
Definition matrix.h:103
constexpr Matrix()
Construct a zero matrix.
Definition matrix.h:35
constexpr Matrix< U, Cols, Rows > transpose() const
Compute the transpose of the matrix.
Definition matrix.h:122
constexpr std::span< T, Cols > operator[](size_t i)
Index to a row in the matrix.
Definition matrix.h:86
std::string toString() const
Assemble and return a string describing the matrix.
Definition matrix.h:59
constexpr std::span< const T, Cols > operator[](size_t i) const
Index to a row in the matrix.
Definition matrix.h:81
constexpr std::span< T, Rows *Cols > data()
Access the matrix data as a linear array.
Definition matrix.h:79
constexpr std::span< const T, Rows *Cols > data() const
Access the matrix data as a linear array.
Definition matrix.h:77
Matrix(std::span< const T, Rows *Cols > data)
Construct a matrix from supplied data.
Definition matrix.h:44
std::optional< T > get() const
Parse the ValueNode as a T value.
Definition value_node.h:211
ListAdapter asList()
Wrap a list ValueNode in an adapter that exposes iterators.
Definition value_node.h:230
Logging infrastructure.
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
Definition log.h:51
Top-level libcamera namespace.
Definition backtrace.h:17
std::ostream & operator<<(std::ostream &out, const Point &p)
Insert a text representation of a Point into an output stream.
Definition geometry.cpp:93
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition matrix.h:152
constexpr Matrix< T, Rows, Cols > operator+(const Matrix< T, Rows, Cols > &m1, const Matrix< T, Rows, Cols > &m2)
Matrix addition.
Definition matrix.h:197
Data structure to manage tree of values.