libcamera  v0.5.1+11-8d2cd0b5
Supporting cameras in Linux since 2019
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
23 
24 namespace libcamera {
25 
27 
28 #ifndef __DOXYGEN__
29 template<typename T, unsigned int Rows,
30  std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
31 #else
32 template<typename T, unsigned int Rows>
33 #endif /* __DOXYGEN__ */
34 class Vector
35 {
36 public:
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, other, std::plus<>{});
77  }
78 
79  constexpr Vector operator+(T scalar) const
80  {
81  return apply(*this, scalar, std::plus<>{});
82  }
83 
84  constexpr Vector operator-(const Vector &other) const
85  {
86  return apply(*this, other, std::minus<>{});
87  }
88 
89  constexpr Vector operator-(T scalar) const
90  {
91  return apply(*this, scalar, std::minus<>{});
92  }
93 
94  constexpr Vector operator*(const Vector &other) const
95  {
96  return apply(*this, other, std::multiplies<>{});
97  }
98 
99  constexpr Vector operator*(T scalar) const
100  {
101  return apply(*this, scalar, std::multiplies<>{});
102  }
103 
104  constexpr Vector operator/(const Vector &other) const
105  {
106  return apply(*this, other, std::divides<>{});
107  }
108 
109  constexpr Vector operator/(T scalar) const
110  {
111  return apply(*this, scalar, std::divides<>{});
112  }
113 
114  Vector &operator+=(const Vector &other)
115  {
116  return apply(other, [](T a, T b) { return a + b; });
117  }
118 
119  Vector &operator+=(T scalar)
120  {
121  return apply(scalar, [](T a, T b) { return a + b; });
122  }
123 
124  Vector &operator-=(const Vector &other)
125  {
126  return apply(other, [](T a, T b) { return a - b; });
127  }
128 
129  Vector &operator-=(T scalar)
130  {
131  return apply(scalar, [](T a, T b) { return a - b; });
132  }
133 
134  Vector &operator*=(const Vector &other)
135  {
136  return apply(other, [](T a, T b) { return a * b; });
137  }
138 
139  Vector &operator*=(T scalar)
140  {
141  return apply(scalar, [](T a, T b) { return a * b; });
142  }
143 
144  Vector &operator/=(const Vector &other)
145  {
146  return apply(other, [](T a, T b) { return a / b; });
147  }
148 
149  Vector &operator/=(T scalar)
150  {
151  return apply(scalar, [](T a, T b) { return a / b; });
152  }
153 
154  constexpr Vector min(const Vector &other) const
155  {
156  return apply(*this, other, [](T a, T b) { return std::min(a, b); });
157  }
158 
159  constexpr Vector min(T scalar) const
160  {
161  return apply(*this, scalar, [](T a, T b) { return std::min(a, b); });
162  }
163 
164  constexpr Vector max(const Vector &other) const
165  {
166  return apply(*this, other, [](T a, T b) { return std::max(a, b); });
167  }
168 
169  constexpr Vector max(T scalar) const
170  {
171  return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); });
172  }
173 
174  constexpr T dot(const Vector<T, Rows> &other) const
175  {
176  T ret = 0;
177  for (unsigned int i = 0; i < Rows; i++)
178  ret += data_[i] * other[i];
179  return ret;
180  }
181 
182 #ifndef __DOXYGEN__
183  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
184 #endif /* __DOXYGEN__ */
185  constexpr const T &x() const { return data_[0]; }
186 #ifndef __DOXYGEN__
187  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
188 #endif /* __DOXYGEN__ */
189  constexpr const T &y() const { return data_[1]; }
190 #ifndef __DOXYGEN__
191  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
192 #endif /* __DOXYGEN__ */
193  constexpr const T &z() const { return data_[2]; }
194 #ifndef __DOXYGEN__
195  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
196 #endif /* __DOXYGEN__ */
197  constexpr T &x() { return data_[0]; }
198 #ifndef __DOXYGEN__
199  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
200 #endif /* __DOXYGEN__ */
201  constexpr T &y() { return data_[1]; }
202 #ifndef __DOXYGEN__
203  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
204 #endif /* __DOXYGEN__ */
205  constexpr T &z() { return data_[2]; }
206 
207 #ifndef __DOXYGEN__
208  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
209 #endif /* __DOXYGEN__ */
210  constexpr const T &r() const { return data_[0]; }
211 #ifndef __DOXYGEN__
212  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
213 #endif /* __DOXYGEN__ */
214  constexpr const T &g() const { return data_[1]; }
215 #ifndef __DOXYGEN__
216  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
217 #endif /* __DOXYGEN__ */
218  constexpr const T &b() const { return data_[2]; }
219 #ifndef __DOXYGEN__
220  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>>
221 #endif /* __DOXYGEN__ */
222  constexpr T &r() { return data_[0]; }
223 #ifndef __DOXYGEN__
224  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>>
225 #endif /* __DOXYGEN__ */
226  constexpr T &g() { return data_[1]; }
227 #ifndef __DOXYGEN__
228  template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>>
229 #endif /* __DOXYGEN__ */
230  constexpr T &b() { return data_[2]; }
231 
232  constexpr double length2() const
233  {
234  double ret = 0;
235  for (unsigned int i = 0; i < Rows; i++)
236  ret += data_[i] * data_[i];
237  return ret;
238  }
239 
240  constexpr double length() const
241  {
242  return std::sqrt(length2());
243  }
244 
245  template<typename R = T>
246  constexpr R sum() const
247  {
248  return std::accumulate(data_.begin(), data_.end(), R{});
249  }
250 
251 private:
252  template<class BinaryOp>
253  static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op)
254  {
255  Vector result;
256  std::transform(lhs.data_.begin(), lhs.data_.end(),
257  rhs.data_.begin(), result.data_.begin(),
258  op);
259 
260  return result;
261  }
262 
263  template<class BinaryOp>
264  static constexpr Vector apply(const Vector &lhs, T rhs, BinaryOp op)
265  {
266  Vector result;
267  std::transform(lhs.data_.begin(), lhs.data_.end(),
268  result.data_.begin(),
269  [&op, rhs](T v) { return op(v, rhs); });
270 
271  return result;
272  }
273 
274  template<class BinaryOp>
275  Vector &apply(const Vector &other, BinaryOp op)
276  {
277  auto itOther = other.data_.begin();
278  std::for_each(data_.begin(), data_.end(),
279  [&op, &itOther](T &v) { v = op(v, *itOther++); });
280 
281  return *this;
282  }
283 
284  template<class BinaryOp>
285  Vector &apply(T scalar, BinaryOp op)
286  {
287  std::for_each(data_.begin(), data_.end(),
288  [&op, scalar](T &v) { v = op(v, scalar); });
289 
290  return *this;
291  }
292 
293  std::array<T, Rows> data_;
294 };
295 
296 template<typename T>
298 
299 template<typename T, typename U, unsigned int Rows, unsigned int Cols>
301 {
302  Vector<std::common_type_t<T, U>, Rows> result;
303 
304  for (unsigned int i = 0; i < Rows; i++) {
305  std::common_type_t<T, U> sum = 0;
306  for (unsigned int j = 0; j < Cols; j++)
307  sum += m[i][j] * v[j];
308  result[i] = sum;
309  }
310 
311  return result;
312 }
313 
314 template<typename T, unsigned int Rows>
315 bool operator==(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs)
316 {
317  for (unsigned int i = 0; i < Rows; i++) {
318  if (lhs[i] != rhs[i])
319  return false;
320  }
321 
322  return true;
323 }
324 
325 template<typename T, unsigned int Rows>
326 bool operator!=(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs)
327 {
328  return !(lhs == rhs);
329 }
330 
331 #ifndef __DOXYGEN__
332 bool vectorValidateYaml(const YamlObject &obj, unsigned int size);
333 #endif /* __DOXYGEN__ */
334 
335 #ifndef __DOXYGEN__
336 template<typename T, unsigned int Rows>
337 std::ostream &operator<<(std::ostream &out, const Vector<T, Rows> &v)
338 {
339  out << "Vector { ";
340  for (unsigned int i = 0; i < Rows; i++) {
341  out << v[i];
342  out << ((i + 1 < Rows) ? ", " : " ");
343  }
344  out << " }";
345 
346  return out;
347 }
348 
349 template<typename T, unsigned int Rows>
350 struct YamlObject::Getter<Vector<T, Rows>> {
351  std::optional<Vector<T, Rows>> get(const YamlObject &obj) const
352  {
353  if (!vectorValidateYaml(obj, Rows))
354  return std::nullopt;
355 
356  Vector<T, Rows> vector;
357 
358  unsigned int i = 0;
359  for (const YamlObject &entry : obj.asList()) {
360  const auto value = entry.get<T>();
361  if (!value)
362  return std::nullopt;
363  vector[i++] = *value;
364  }
365 
366  return vector;
367  }
368 };
369 #endif /* __DOXYGEN__ */
370 
371 } /* namespace libcamera */
bool operator!=(const Vector< T, Rows > &lhs, const Vector< T, Rows > &rhs)
Compare vectors for inequality.
Definition: vector.h:326
constexpr const T & g() const
Convenience function to access the second element of the vector.
Definition: vector.h:214
constexpr const T & b() const
Convenience function to access the third element of the vector.
Definition: vector.h:218
constexpr R sum() const
Calculate the sum of all the vector elements.
Definition: vector.h:246
constexpr Vector()=default
Construct an uninitialized vector.
constexpr Vector min(const Vector &other) const
Calculate the minimum of this vector and other element-wise.
Definition: vector.h:154
constexpr const T & r() const
Convenience function to access the first element of the vector.
Definition: vector.h:210
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs)
Compare color spaces for equality.
Definition: color_space.cpp:506
constexpr Vector(const std::array< T, Rows > &data)
Construct vector from supplied data.
Definition: vector.h:44
constexpr T & r()
Convenience function to access the first element of the vector.
Definition: vector.h:222
constexpr Vector operator+(const Vector &other) const
Calculate the sum of this vector and other element-wise.
Definition: vector.h:74
Top-level libcamera namespace.
Definition: backtrace.h:17
ListAdapter asList() const
Wrap a list YamlObject in an adapter that exposes iterators.
Definition: yaml_parser.h:206
constexpr const T & y() const
Convenience function to access the second element of the vector.
Definition: vector.h:189
constexpr Vector min(T scalar) const
Calculate the minimum of this vector and scalar element-wise.
Definition: vector.h:159
constexpr Vector operator/(T scalar) const
Calculate the quotient of this vector and scalar element-wise.
Definition: vector.h:109
#define ASSERT(condition)
Abort program execution if assertion fails.
Vector & operator/=(T scalar)
Divide this vector by scalar element-wise.
Definition: vector.h:149
constexpr Vector max(const Vector &other) const
Calculate the maximum of this vector and other element-wise.
Definition: vector.h:164
Matrix class.
Definition: matrix.h:30
constexpr T & g()
Convenience function to access the second element of the vector.
Definition: vector.h:226
Vector & operator+=(const Vector &other)
Add other element-wise to this vector.
Definition: vector.h:114
constexpr T & x()
Convenience function to access the first element of the vector.
Definition: vector.h:197
const T & operator[](size_t i) const
Index to an element in the vector.
Definition: vector.h:54
constexpr Vector operator*(T scalar) const
Calculate the product of this vector and scalar element-wise.
Definition: vector.h:99
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
constexpr Vector< T, Rows > operator-() const
Negate a Vector by negating both all of its coordinates.
Definition: vector.h:66
constexpr T & b()
Convenience function to access the third element of the vector.
Definition: vector.h:230
constexpr const T & x() const
Convenience function to access the first element of the vector.
Definition: vector.h:185
constexpr double length2() const
Get the squared length of the vector.
Definition: vector.h:232
Matrix class.
Vector & operator*=(const Vector &other)
Multiply this vector by other element-wise.
Definition: vector.h:134
constexpr Vector(const Span< const T, Rows > data)
Construct vector from supplied data.
Definition: vector.h:49
constexpr double length() const
Get the length of the vector.
Definition: vector.h:240
A class representing the tree structure of the YAML content.
Definition: yaml_parser.h:27
T & operator[](size_t i)
Index to an element in the vector.
Definition: vector.h:60
constexpr Vector operator-(T scalar) const
Calculate the difference of this vector and scalar element-wise.
Definition: vector.h:89
constexpr T & z()
Convenience function to access the third element of the vector.
Definition: vector.h:205
constexpr Vector operator+(T scalar) const
Calculate the sum of this vector and scalar element-wise.
Definition: vector.h:79
constexpr T & y()
Convenience function to access the second element of the vector.
Definition: vector.h:201
Vector & operator/=(const Vector &other)
Divide this vector by other element-wise.
Definition: vector.h:144
constexpr Vector operator-(const Vector &other) const
Calculate the difference of this vector and other element-wise.
Definition: vector.h:84
Vector & operator-=(const Vector &other)
Subtract other element-wise from this vector.
Definition: vector.h:124
constexpr Vector operator*(const Vector &other) const
Calculate the product of this vector and other element-wise.
Definition: vector.h:94
Logging infrastructure.
constexpr T dot(const Vector< T, Rows > &other) const
Compute the dot product.
Definition: vector.h:174
constexpr const T & z() const
Convenience function to access the third element of the vector.
Definition: vector.h:193
Vector & operator*=(T scalar)
Multiply this vector by scalar element-wise.
Definition: vector.h:139
Vector class.
Definition: vector.h:34
A YAML parser helper.
constexpr Vector max(T scalar) const
Calculate the maximum of this vector and scalar element-wise.
Definition: vector.h:169
constexpr Vector(T scalar)
Construct a vector filled with a scalar value.
Definition: vector.h:39
Vector & operator+=(T scalar)
Add scalar element-wise to this vector.
Definition: vector.h:119
Vector & operator-=(T scalar)
Subtract scalar element-wise from this vector.
Definition: vector.h:129
constexpr Vector operator/(const Vector &other) const
Calculate the quotient of this vector and other element-wise.
Definition: vector.h:104