libcamera v0.5.1
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 <sstream>
11#include <type_traits>
12#include <vector>
13
14#include <libcamera/base/log.h>
15#include <libcamera/base/span.h>
16
18
19namespace libcamera {
20
22
23#ifndef __DOXYGEN__
24template<typename T>
25bool matrixInvert(Span<const T> dataIn, Span<T> dataOut, unsigned int dim,
26 Span<T> scratchBuffer, 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(const 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 const 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 Span<const T, Rows * Cols> data() const { return data_; }
78
79 constexpr Span<const T, Cols> operator[](size_t i) const
80 {
81 return Span<const T, Cols>{ &data_.data()[i * Cols], Cols };
82 }
83
84 constexpr Span<T, Cols> operator[](size_t i)
85 {
86 return Span<T, Cols>{ &data_.data()[i * Cols], Cols };
87 }
88
89#ifndef __DOXYGEN__
90 template<typename U, std::enable_if_t<std::is_arithmetic_v<U>>>
91#else
92 template<typename U>
93#endif /* __DOXYGEN__ */
95 {
96 for (unsigned int i = 0; i < Rows * Cols; i++)
97 data_[i] *= d;
98 return *this;
99 }
100
101 Matrix<T, Rows, Cols> inverse(bool *ok = nullptr) const
102 {
103 static_assert(Rows == Cols, "Matrix must be square");
104
106 std::array<T, Rows * Cols * 2> scratchBuffer;
107 std::array<unsigned int, Rows> swapBuffer;
108 bool res = matrixInvert(Span<const T>(data_),
109 Span<T>(inverse.data_),
110 Rows,
111 Span<T>(scratchBuffer),
112 Span<unsigned int>(swapBuffer));
113 if (ok)
114 *ok = res;
115 return inverse;
116 }
117
118private:
119 /*
120 * \todo The initializer is only necessary for the constructor to be
121 * constexpr in C++17. Remove the initializer as soon as we are on
122 * C++20.
123 */
124 std::array<T, Rows * Cols> data_ = {};
125};
126
127#ifndef __DOXYGEN__
128template<typename T, typename U, unsigned int Rows, unsigned int Cols,
129 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
130#else
131template<typename T, typename U, unsigned int Rows, unsigned int Cols>
132#endif /* __DOXYGEN__ */
134{
136
137 for (unsigned int i = 0; i < Rows; i++) {
138 for (unsigned int j = 0; j < Cols; j++)
139 result[i][j] = d * m[i][j];
140 }
141
142 return result;
143}
144
145#ifndef __DOXYGEN__
146template<typename T, typename U, unsigned int Rows, unsigned int Cols,
147 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
148#else
149template<typename T, typename U, unsigned int Rows, unsigned int Cols>
150#endif /* __DOXYGEN__ */
152{
153 return d * m;
154}
155
156template<typename T1, unsigned int R1, unsigned int C1, typename T2, unsigned int R2, unsigned int C2>
158 const Matrix<T2, R2, C2> &m2)
159{
160 static_assert(C1 == R2, "Matrix dimensions must match for multiplication");
161 Matrix<std::common_type_t<T1, T2>, R1, C2> result;
162
163 for (unsigned int i = 0; i < R1; i++) {
164 for (unsigned int j = 0; j < C2; j++) {
165 std::common_type_t<T1, T2> sum = 0;
166
167 for (unsigned int k = 0; k < C1; k++)
168 sum += m1[i][k] * m2[k][j];
169
170 result[i][j] = sum;
171 }
172 }
173
174 return result;
175}
176
177template<typename T, unsigned int Rows, unsigned int Cols>
179{
181
182 for (unsigned int i = 0; i < Rows; i++) {
183 for (unsigned int j = 0; j < Cols; j++)
184 result[i][j] = m1[i][j] + m2[i][j];
185 }
186
187 return result;
188}
189
190#ifndef __DOXYGEN__
191bool matrixValidateYaml(const YamlObject &obj, unsigned int size);
192#endif /* __DOXYGEN__ */
193
194#ifndef __DOXYGEN__
195template<typename T, unsigned int Rows, unsigned int Cols>
196std::ostream &operator<<(std::ostream &out, const Matrix<T, Rows, Cols> &m)
197{
198 out << m.toString();
199 return out;
200}
201
202template<typename T, unsigned int Rows, unsigned int Cols>
203struct YamlObject::Getter<Matrix<T, Rows, Cols>> {
204 std::optional<Matrix<T, Rows, Cols>> get(const YamlObject &obj) const
205 {
206 if (!matrixValidateYaml(obj, Rows * Cols))
207 return std::nullopt;
208
209 Matrix<T, Rows, Cols> matrix;
210 T *data = &matrix[0][0];
211
212 unsigned int i = 0;
213 for (const YamlObject &entry : obj.asList()) {
214 const auto value = entry.get<T>();
215 if (!value)
216 return std::nullopt;
217
218 data[i++] = *value;
219 }
220
221 return matrix;
222 }
223};
224#endif /* __DOXYGEN__ */
225
226} /* namespace libcamera */
Matrix class.
Definition matrix.h:31
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:94
constexpr Span< const T, Cols > operator[](size_t i) const
Index to a row in the matrix.
Definition matrix.h:79
static constexpr Matrix identity()
Construct an identity matrix.
Definition matrix.h:49
const std::string toString() const
Assemble and return a string describing the matrix.
Definition matrix.h:59
Matrix< T, Rows, Cols > inverse(bool *ok=nullptr) const
Compute the inverse of the matrix.
Definition matrix.h:101
constexpr Span< T, Cols > operator[](size_t i)
Index to a row in the matrix.
Definition matrix.h:84
constexpr Span< const T, Rows *Cols > data() const
Access the matrix data as a linear array.
Definition matrix.h:77
Matrix(const Span< const T, Rows *Cols > data)
Construct a matrix from supplied data.
Definition matrix.h:44
constexpr Matrix()
Construct a zero matrix.
Definition matrix.h:35
std::optional< T > get() const
Parse the YamlObject as a T value.
Definition yaml_parser.h:175
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:91
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition matrix.h:133
constexpr Matrix< T, Rows, Cols > operator+(const Matrix< T, Rows, Cols > &m1, const Matrix< T, Rows, Cols > &m2)
Matrix addition.
Definition matrix.h:178
A YAML parser helper.