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