libcamera v0.5.0+59-d83ff0a4
Supporting cameras in Linux since 2019
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 <vector>
12
13#include <libcamera/base/log.h>
14#include <libcamera/base/span.h>
15
17
18namespace libcamera {
19
21
22#ifndef __DOXYGEN__
23template<typename T, unsigned int Rows, unsigned int Cols,
24 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
25#else
26template<typename T, unsigned int Rows, unsigned int Cols>
27#endif /* __DOXYGEN__ */
28class Matrix
29{
30public:
32 {
33 data_.fill(static_cast<T>(0));
34 }
35
36 Matrix(const std::array<T, Rows * Cols> &data)
37 {
38 std::copy(data.begin(), data.end(), data_.begin());
39 }
40
42 {
43 Matrix ret;
44 for (size_t i = 0; i < std::min(Rows, Cols); i++)
45 ret[i][i] = static_cast<T>(1);
46 return ret;
47 }
48
49 ~Matrix() = default;
50
51 const std::string toString() const
52 {
53 std::stringstream out;
54
55 out << "Matrix { ";
56 for (unsigned int i = 0; i < Rows; i++) {
57 out << "[ ";
58 for (unsigned int j = 0; j < Cols; j++) {
59 out << (*this)[i][j];
60 out << ((j + 1 < Cols) ? ", " : " ");
61 }
62 out << ((i + 1 < Rows) ? "], " : "]");
63 }
64 out << " }";
65
66 return out.str();
67 }
68
69 Span<const T, Rows * Cols> data() const { return data_; }
70
71 Span<const T, Cols> operator[](size_t i) const
72 {
73 return Span<const T, Cols>{ &data_.data()[i * Cols], Cols };
74 }
75
76 Span<T, Cols> operator[](size_t i)
77 {
78 return Span<T, Cols>{ &data_.data()[i * Cols], Cols };
79 }
80
81#ifndef __DOXYGEN__
82 template<typename U, std::enable_if_t<std::is_arithmetic_v<U>>>
83#else
84 template<typename U>
85#endif /* __DOXYGEN__ */
87 {
88 for (unsigned int i = 0; i < Rows * Cols; i++)
89 data_[i] *= d;
90 return *this;
91 }
92
93private:
94 std::array<T, Rows * Cols> data_;
95};
96
97#ifndef __DOXYGEN__
98template<typename T, typename U, unsigned int Rows, unsigned int Cols,
99 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
100#else
101template<typename T, typename U, unsigned int Rows, unsigned int Cols>
102#endif /* __DOXYGEN__ */
104{
106
107 for (unsigned int i = 0; i < Rows; i++) {
108 for (unsigned int j = 0; j < Cols; j++)
109 result[i][j] = d * m[i][j];
110 }
111
112 return result;
113}
114
115#ifndef __DOXYGEN__
116template<typename T, typename U, unsigned int Rows, unsigned int Cols,
117 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
118#else
119template<typename T, typename U, unsigned int Rows, unsigned int Cols>
120#endif /* __DOXYGEN__ */
122{
123 return d * m;
124}
125
126#ifndef __DOXYGEN__
127template<typename T,
128 unsigned int R1, unsigned int C1,
129 unsigned int R2, unsigned int C2,
130 std::enable_if_t<C1 == R2> * = nullptr>
131#else
132template<typename T, unsigned int R1, unsigned int C1, unsigned int R2, unsigned in C2>
133#endif /* __DOXYGEN__ */
135{
136 Matrix<T, R1, C2> result;
137
138 for (unsigned int i = 0; i < R1; i++) {
139 for (unsigned int j = 0; j < C2; j++) {
140 T sum = 0;
141
142 for (unsigned int k = 0; k < C1; k++)
143 sum += m1[i][k] * m2[k][j];
144
145 result[i][j] = sum;
146 }
147 }
148
149 return result;
150}
151
152template<typename T, unsigned int Rows, unsigned int Cols>
154{
156
157 for (unsigned int i = 0; i < Rows; i++) {
158 for (unsigned int j = 0; j < Cols; j++)
159 result[i][j] = m1[i][j] + m2[i][j];
160 }
161
162 return result;
163}
164
165#ifndef __DOXYGEN__
166bool matrixValidateYaml(const YamlObject &obj, unsigned int size);
167#endif /* __DOXYGEN__ */
168
169#ifndef __DOXYGEN__
170template<typename T, unsigned int Rows, unsigned int Cols>
171std::ostream &operator<<(std::ostream &out, const Matrix<T, Rows, Cols> &m)
172{
173 out << m.toString();
174 return out;
175}
176
177template<typename T, unsigned int Rows, unsigned int Cols>
178struct YamlObject::Getter<Matrix<T, Rows, Cols>> {
179 std::optional<Matrix<T, Rows, Cols>> get(const YamlObject &obj) const
180 {
181 if (!matrixValidateYaml(obj, Rows * Cols))
182 return std::nullopt;
183
184 Matrix<T, Rows, Cols> matrix;
185 T *data = &matrix[0][0];
186
187 unsigned int i = 0;
188 for (const YamlObject &entry : obj.asList()) {
189 const auto value = entry.get<T>();
190 if (!value)
191 return std::nullopt;
192
193 data[i++] = *value;
194 }
195
196 return matrix;
197 }
198};
199#endif /* __DOXYGEN__ */
200
201} /* namespace libcamera */
Matrix class.
Definition: matrix.h:29
static Matrix identity()
Construct an identity matrix.
Definition: matrix.h:41
Matrix(const std::array< T, Rows *Cols > &data)
Construct a matrix from supplied data.
Definition: matrix.h:36
Matrix< T, Rows, Cols > & operator*=(U d)
Multiply the matrix by a scalar in-place.
Definition: matrix.h:86
Matrix()
Construct a zero matrix.
Definition: matrix.h:31
Span< T, Cols > operator[](size_t i)
Definition: matrix.h:76
const std::string toString() const
Assemble and return a string describing the matrix.
Definition: matrix.h:51
Span< const T, Cols > operator[](size_t i) const
Index to a row in the matrix.
Definition: matrix.h:71
Span< const T, Rows *Cols > data() const
Access the matrix data as a linear array.
Definition: matrix.h:69
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.
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:103
Matrix< T, Rows, Cols > operator+(const Matrix< T, Rows, Cols > &m1, const Matrix< T, Rows, Cols > &m2)
Matrix addition.
Definition: matrix.h:153
A YAML parser helper.