libcamera: include/libcamera/internal/vector.h Source File

libcamera v0.7.2 Supporting cameras in Linux since 2019

Loading...
Searching...
No Matches
vector.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 * Vector and related operations
6 */
7#pragma once
8
9#include <algorithm>
10#include <array>
11#include <cmath>
12#include <functional>
13#include <numeric>
14#include <optional>
15#include <ostream>
16#include <type_traits>
17
18#include <libcamera/base/log.h>
19#include <libcamera/base/span.h>
20
21#include "libcamera/internal/matrix.h"
22#include "libcamera/internal/value_node.h"
23
24namespace libcamera {
25
26 LOG_DECLARE_CATEGORY(Vector)
27
28#ifndef __DOXYGEN__
29template<typename T, unsigned int Rows,
30 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
31#else
32template<typename T, unsigned int Rows>
33#endif /* __DOXYGEN__ */
34 class Vector
35{
36public:
37 constexpr Vector() = default;
38
39 constexpr explicit Vector(T scalar)
40 {
41 data_.fill(scalar);
42 }
43
44 constexpr Vector(const std::array<T, Rows> &data)
45 {
46 std::copy(data.begin(), data.end(), data_.begin());
47 }
48
49 constexpr Vector(const Span<const T, Rows> data)
50 {
51 std::copy(data.begin(), data.end(), data_.begin());
52 }
53
54 const T &operator[](size_t i) const
55 {
56 ASSERT(i < data_.size());
57 return data_[i];
58 }
59
60 T &operator[](size_t i)
61 {
62 ASSERT(i < data_.size());
63 return data_[i];
64 }
65
66 constexpr Vector<T, Rows> operator-() const
67 {
68 Vector<T, Rows> ret;
69 for (unsigned int i = 0; i < Rows; i++)
70 ret[i] = -data_[i];
71 return ret;
72 }
73
74 constexpr Vector operator+(const Vector &other) const
75 {
76 return apply(*this, std::plus<>{}, other);
77 }
78
79 constexpr Vector operator+(T scalar) const
80 {
81 return apply(*this, std::plus<>{}, scalar);
82 }
83
84 constexpr Vector operator-(const Vector &other) const
85 {
86 return apply(*this, std::minus<>{}, other);
87 }
88
89 constexpr Vector operator-(T scalar) const
90 {
91 return apply(*this, std::minus<>{}, scalar);
92 }
93
94 constexpr Vector operator*(const Vector &other) const
95 {
96 return apply(*this, std::multiplies<>{}, other);
97 }
98
99 constexpr Vector operator*(T scalar) const
100 {
101 return apply(*this, std::multiplies<>{}, scalar);
102 }
103
104 constexpr Vector operator/(const Vector &other) const
105 {
106 return apply(*this, std::divides<>{}, other);
107 }
108
109 constexpr Vector operator/(T scalar) const
110 {
111 return apply(*this, std::divides<>{}, scalar);
112 }
113
114 constexpr Vector operator>>(unsigned int shift) const
115 {
116 static_assert(std::is_integral_v<T>,
117 "Vector::operator>> requires an integer element type");
118 return apply(*this, [](T a, unsigned int b) { return a >> b; }, shift);
119 }
120
121 Vector &operator+=(const Vector &other)
122 {
123 return apply(std::plus<>{}, other);
124 }
125
126 Vector &operator+=(T scalar)
127 {
128 return apply(std::plus<>{}, scalar);
129 }
130
131 Vector &operator-=(const Vector &other)
132 {
133 return apply(std::minus<>{}, other);
134 }
135
136 Vector &operator-=(T scalar)
137 {
138 return apply(std::minus<>{}, scalar);
139 }
140
141 Vector &operator*=(const Vector &other)
142 {
143 return apply(std::multiplies<>{}, other);
144 }
145
146 Vector &operator*=(T scalar)
147 {
148 return apply(std::multiplies<>{}, scalar);
149 }
150
151 Vector &operator/=(const Vector &other)
152 {
153 return apply(std::divides<>{}, other);
154 }
155
156 Vector &operator/=(T scalar)
157 {
158 return apply(std::divides<>{}, scalar);
159 }
160
161 Vector &operator>>=(unsigned int shift)
162 {
163 static_assert(std::is_integral_v<T>,
164 "Vector::operator>>= requires an integer element type");
165 return apply([](T a, unsigned int b) { return a >> b; }, shift);
166 }
167
168 constexpr Vector min(const Vector &other) const
169 {
170 return apply(*this, [](T a, T b) { return std::min(a, b); }, other);
171 }
172
173 constexpr Vector min(T scalar) const
174 {
175 return apply(*this, [](T a, T b) { return std::min(a, b); }, scalar);
176 }
177
178 constexpr Vector max(const Vector &other) const
179 {
180 return apply(*this, [](T a, T b) { return std::max(a, b); }, other);
181 }
182
183 constexpr Vector max(T scalar) const
184 {
185 return apply(*this, [](T a, T b) -> T { return std::max(a, b); }, scalar);
186 }
187
188 constexpr Vector clamp(T low, T high) const
189 {
190 return apply(*this,
191 [](T v, T lo, T hi) -> T { return std::clamp(v, lo, hi); },
192 low, high);
193 }
194
195 constexpr T dot(const Vector<T, Rows> &other) const
196 {
197 T ret = 0;
198 for (unsigned int i = 0; i < Rows; i++)
199 ret += data_[i] * other[i];
200 return ret;
201 }
202
203#ifndef __DOXYGEN__
204 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
205#endif /* __DOXYGEN__ */
206 constexpr const T &x() const { return data_[0]; }
207#ifndef __DOXYGEN__
208 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
209#endif /* __DOXYGEN__ */
210 constexpr const T &y() const { return data_[1]; }
211#ifndef __DOXYGEN__
212 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
213#endif /* __DOXYGEN__ */
214 constexpr const T &z() const { return data_[2]; }
215#ifndef __DOXYGEN__
216 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
217#endif /* __DOXYGEN__ */
218 constexpr T &x() { return data_[0]; }
219#ifndef __DOXYGEN__
220 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
221#endif /* __DOXYGEN__ */
222 constexpr T &y() { return data_[1]; }
223#ifndef __DOXYGEN__
224 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
225#endif /* __DOXYGEN__ */
226 constexpr T &z() { return data_[2]; }
227
228#ifndef __DOXYGEN__
229 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
230#endif /* __DOXYGEN__ */
231 constexpr const T &r() const { return data_[0]; }
232#ifndef __DOXYGEN__
233 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
234#endif /* __DOXYGEN__ */
235 constexpr const T &g() const { return data_[1]; }
236#ifndef __DOXYGEN__
237 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
238#endif /* __DOXYGEN__ */
239 constexpr const T &b() const { return data_[2]; }
240#ifndef __DOXYGEN__
241 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
242#endif /* __DOXYGEN__ */
243 constexpr T &r() { return data_[0]; }
244#ifndef __DOXYGEN__
245 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
246#endif /* __DOXYGEN__ */
247 constexpr T &g() { return data_[1]; }
248#ifndef __DOXYGEN__
249 template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
250#endif /* __DOXYGEN__ */
251 constexpr T &b() { return data_[2]; }
252
253 constexpr double length2() const
254 {
255 double ret = 0;
256 for (unsigned int i = 0; i < Rows; i++)
257 ret += data_[i] * data_[i];
258 return ret;
259 }
260
261 constexpr double length() const
262 {
263 return std::sqrt(length2());
264 }
265
266 template<typename R = T>
267 constexpr R sum() const
268 {
269 return std::accumulate(data_.begin(), data_.end(), R{});
270 }
271
272private:
273 template<typename BinaryOp>
274 static constexpr Vector apply(const Vector &lhs, BinaryOp op, const Vector &rhs)
275 {
276 Vector result;
277 std::transform(lhs.data_.begin(), lhs.data_.end(),
278 rhs.data_.begin(), result.data_.begin(),
279 op);
280
281 return result;
282 }
283
284 template<typename Op, typename... U>
285 static constexpr Vector apply(const Vector &vector, Op op, U... scalar)
286 {
287 Vector result;
288 std::transform(vector.data_.begin(), vector.data_.end(),
289 result.data_.begin(),
290 [&op, scalar...](T v) { return op(v, scalar...); });
291
292 return result;
293 }
294
295 template<typename BinaryOp>
296 Vector &apply(BinaryOp op, const Vector &other)
297 {
298 auto itOther = other.data_.begin();
299 std::for_each(data_.begin(), data_.end(),
300 [&op, &itOther](T &v) { v = op(v, *itOther++); });
301
302 return *this;
303 }
304
305 template<typename Op, typename... U>
306 Vector &apply(Op op, U... scalar)
307 {
308 std::for_each(data_.begin(), data_.end(),
309 [&op, scalar...](T &v) { v = op(v, scalar...); });
310
311 return *this;
312 }
313
314 std::array<T, Rows> data_;
315};
316
317template<typename T>
318 using RGB = Vector<T, 3>;
319
320template<typename T, typename U, unsigned int Rows, unsigned int Cols>
321 Vector<std::common_type_t<T, U>, Rows> operator*(const Matrix<T, Rows, Cols> &m, const Vector<U, Cols> &v)
322{
323 Vector<std::common_type_t<T, U>, Rows> result;
324
325 for (unsigned int i = 0; i < Rows; i++) {
326 std::common_type_t<T, U> sum = 0;
327 for (unsigned int j = 0; j < Cols; j++)
328 sum += m[i][j] * v[j];
329 result[i] = sum;
330 }
331
332 return result;
333}
334
335template<typename T, unsigned int Rows>
336 bool operator==(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs)
337{
338 for (unsigned int i = 0; i < Rows; i++) {
339 if (lhs[i] != rhs[i])
340 return false;
341 }
342
343 return true;
344}
345
346template<typename T, unsigned int Rows>
347 bool operator!=(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs)
348{
349 return !(lhs == rhs);
350}
351
352#ifndef __DOXYGEN__
353bool vectorValidateValueNode(const ValueNode &obj, unsigned int size);
354
355template<typename T, unsigned int Rows>
356std::ostream &operator<<(std::ostream &out, const Vector<T, Rows> &v)
357{
358 out << "Vector { ";
359 for (unsigned int i = 0; i < Rows; i++) {
360 out << v[i];
361 out << ((i + 1 < Rows) ? ", " : " ");
362 }
363 out << " }";
364
365 return out;
366}
367
368template<typename T, unsigned int Rows>
369struct ValueNode::Accessor<Vector<T, Rows>> {
370 std::optional<Vector<T, Rows>> get(const ValueNode &obj) const
371 {
372 if (!vectorValidateValueNode(obj, Rows))
373 return std::nullopt;
374
375 Vector<T, Rows> vector;
376
377 unsigned int i = 0;
378 for (const ValueNode &entry : obj.asList()) {
379 const auto value = entry.get<T>();
380 if (!value)
381 return std::nullopt;
382 vector[i++] = *value;
383 }
384
385 return vector;
386 }
387};
388#endif /* __DOXYGEN__ */
389
390} /* namespace libcamera */
libcamera::Matrix
Matrix class.
Definition matrix.h:31
libcamera::ValueNode::get
std::optional< T > get() const
Parse the ValueNode as a T value.
Definition value_node.h:211
libcamera::Vector
Vector class.
Definition vector.h:35
libcamera::Vector::length2
constexpr double length2() const
Get the squared length of the vector.
Definition vector.h:253
libcamera::Vector::operator/
constexpr Vector operator/(const Vector &other) const
Calculate the quotient of this vector and other element-wise.
Definition vector.h:104
libcamera::Vector< T, 3 >::b
constexpr const T & b() const
Definition vector.h:239
libcamera::Vector::operator+
constexpr Vector operator+(const Vector &other) const
Calculate the sum of this vector and other element-wise.
Definition vector.h:74
libcamera::Vector::g
constexpr T & g()
Convenience function to access the second element of the vector.
Definition vector.h:247
libcamera::Vector::length
constexpr double length() const
Get the length of the vector.
Definition vector.h:261
libcamera::Vector::r
constexpr T & r()
Convenience function to access the first element of the vector.
Definition vector.h:243
libcamera::Vector::b
constexpr T & b()
Convenience function to access the third element of the vector.
Definition vector.h:251
libcamera::Vector::Vector
constexpr Vector(const std::array< T, Rows > &data)
Construct vector from supplied data.
Definition vector.h:44
libcamera::Vector::min
constexpr Vector min(const Vector &other) const
Calculate the minimum of this vector and other element-wise.
Definition vector.h:168
libcamera::Vector::operator>>
constexpr Vector operator>>(unsigned int shift) const
Right-shift each element of this vector by shift bits.
Definition vector.h:114
libcamera::Vector::y
constexpr const T & y() const
Convenience function to access the second element of the vector.
Definition vector.h:210
libcamera::Vector::z
constexpr T & z()
Convenience function to access the third element of the vector.
Definition vector.h:226
libcamera::Vector::operator+=
Vector & operator+=(const Vector &other)
Add other element-wise to this vector.
Definition vector.h:121
libcamera::Vector::operator-
constexpr Vector< T, Rows > operator-() const
Negate a Vector by negating both all of its coordinates.
Definition vector.h:66
libcamera::Vector::operator[]
const T & operator[](size_t i) const
Index to an element in the vector.
Definition vector.h:54
libcamera::Vector::z
constexpr const T & z() const
Convenience function to access the third element of the vector.
Definition vector.h:214
libcamera::Vector::Vector
constexpr Vector(T scalar)
Construct a vector filled with a scalar value.
Definition vector.h:39
libcamera::Vector::min
constexpr Vector min(T scalar) const
Calculate the minimum of this vector and scalar element-wise.
Definition vector.h:173
libcamera::Vector::max
constexpr Vector max(const Vector &other) const
Calculate the maximum of this vector and other element-wise.
Definition vector.h:178
libcamera::Vector::operator-=
Vector & operator-=(T scalar)
Subtract scalar element-wise from this vector.
Definition vector.h:136
libcamera::Vector::operator/=
Vector & operator/=(T scalar)
Divide this vector by scalar element-wise.
Definition vector.h:156
libcamera::Vector::operator/=
Vector & operator/=(const Vector &other)
Divide this vector by other element-wise.
Definition vector.h:151
libcamera::Vector::Vector
constexpr Vector()=default
Construct an uninitialized vector.
libcamera::Vector::x
constexpr T & x()
Convenience function to access the first element of the vector.
Definition vector.h:218
libcamera::Vector::operator*
constexpr Vector operator*(const Vector &other) const
Calculate the product of this vector and other element-wise.
Definition vector.h:94
libcamera::Vector::operator>>=
Vector & operator>>=(unsigned int shift)
Right-shift each element of this vector by shift bits in place.
Definition vector.h:161
libcamera::Vector::y
constexpr T & y()
Convenience function to access the second element of the vector.
Definition vector.h:222
libcamera::Vector::sum
constexpr R sum() const
Calculate the sum of all the vector elements.
Definition vector.h:267
libcamera::Vector::x
constexpr const T & x() const
Convenience function to access the first element of the vector.
Definition vector.h:206
libcamera::Vector::operator/
constexpr Vector operator/(T scalar) const
Calculate the quotient of this vector and scalar element-wise.
Definition vector.h:109
libcamera::Vector::operator+
constexpr Vector operator+(T scalar) const
Calculate the sum of this vector and scalar element-wise.
Definition vector.h:79
libcamera::Vector::r
constexpr const T & r() const
Convenience function to access the first element of the vector.
Definition vector.h:231
libcamera::Vector::operator*=
Vector & operator*=(T scalar)
Multiply this vector by scalar element-wise.
Definition vector.h:146
libcamera::Vector::max
constexpr Vector max(T scalar) const
Calculate the maximum of this vector and scalar element-wise.
Definition vector.h:183
libcamera::Vector::operator-
constexpr Vector operator-(T scalar) const
Calculate the difference of this vector and scalar element-wise.
Definition vector.h:89
libcamera::Vector::clamp
constexpr Vector clamp(T low, T high) const
Clamp the vector element-wise between low and high.
Definition vector.h:188
libcamera::Vector::operator-
constexpr Vector operator-(const Vector &other) const
Calculate the difference of this vector and other element-wise.
Definition vector.h:84
libcamera::Vector::operator-=
Vector & operator-=(const Vector &other)
Subtract other element-wise from this vector.
Definition vector.h:131
libcamera::Vector::operator+=
Vector & operator+=(T scalar)
Add scalar element-wise to this vector.
Definition vector.h:126
libcamera::Vector::Vector
constexpr Vector(const Span< const T, Rows > data)
Construct vector from supplied data.
Definition vector.h:49
libcamera::Vector::operator*=
Vector & operator*=(const Vector &other)
Multiply this vector by other element-wise.
Definition vector.h:141
libcamera::Vector::operator*
constexpr Vector operator*(T scalar) const
Calculate the product of this vector and scalar element-wise.
Definition vector.h:99
libcamera::Vector::g
constexpr const T & g() const
Convenience function to access the second element of the vector.
Definition vector.h:235
libcamera::Vector::dot
constexpr T dot(const Vector< T, Rows > &other) const
Compute the dot product.
Definition vector.h:195
libcamera::Vector::operator[]
T & operator[](size_t i)
Index to an element in the vector.
Definition vector.h:60
log.h
Logging infrastructure.
LOG_DECLARE_CATEGORY
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
Definition log.h:51
ASSERT
#define ASSERT(condition)
Abort program execution if assertion fails.
Definition log.h:159
matrix.h
Matrix class.
libcamera
Top-level libcamera namespace.
Definition backtrace.h:17
libcamera::operator<<
std::ostream & operator<<(std::ostream &out, const Point &p)
Insert a text representation of a Point into an output stream.
Definition geometry.cpp:93
libcamera::operator*
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition matrix.h:133
libcamera::RGB
Vector< T, 3 > RGB
A Vector of 3 elements representing an RGB pixel value.
Definition vector.h:318
value_node.h
Data structure to manage tree of values.