diff options
Diffstat (limited to 'src/ipa/libipa/vector.h')
-rw-r--r-- | src/ipa/libipa/vector.h | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h new file mode 100644 index 00000000..8612a06a --- /dev/null +++ b/src/ipa/libipa/vector.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com> + * + * Vector and related operations + */ +#pragma once + +#include <array> +#include <cmath> +#include <optional> +#include <ostream> + +#include <libcamera/base/log.h> +#include <libcamera/base/span.h> + +#include "libcamera/internal/yaml_parser.h" + +#include "matrix.h" + +namespace libcamera { + +LOG_DECLARE_CATEGORY(Vector) + +namespace ipa { + +#ifndef __DOXYGEN__ +template<typename T, unsigned int Rows, + std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr> +#else +template<typename T, unsigned int Rows> +#endif /* __DOXYGEN__ */ +class Vector +{ +public: + constexpr Vector() = default; + + constexpr Vector(const std::array<T, Rows> &data) + { + for (unsigned int i = 0; i < Rows; i++) + data_[i] = data[i]; + } + + const T &operator[](size_t i) const + { + ASSERT(i < data_.size()); + return data_[i]; + } + + T &operator[](size_t i) + { + ASSERT(i < data_.size()); + return data_[i]; + } + +#ifndef __DOXYGEN__ + template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 1>> +#endif /* __DOXYGEN__ */ + constexpr T x() const + { + return data_[0]; + } + +#ifndef __DOXYGEN__ + template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 2>> +#endif /* __DOXYGEN__ */ + constexpr T y() const + { + return data_[1]; + } + +#ifndef __DOXYGEN__ + template<bool Dependent = false, typename = std::enable_if_t<Dependent || Rows >= 3>> +#endif /* __DOXYGEN__ */ + constexpr T z() const + { + return data_[2]; + } + + constexpr Vector<T, Rows> operator-() const + { + Vector<T, Rows> ret; + for (unsigned int i = 0; i < Rows; i++) + ret[i] = -data_[i]; + return ret; + } + + constexpr Vector<T, Rows> operator-(const Vector<T, Rows> &other) const + { + Vector<T, Rows> ret; + for (unsigned int i = 0; i < Rows; i++) + ret[i] = data_[i] - other[i]; + return ret; + } + + constexpr Vector<T, Rows> operator+(const Vector<T, Rows> &other) const + { + Vector<T, Rows> ret; + for (unsigned int i = 0; i < Rows; i++) + ret[i] = data_[i] + other[i]; + return ret; + } + + constexpr T operator*(const Vector<T, Rows> &other) const + { + T ret = 0; + for (unsigned int i = 0; i < Rows; i++) + ret += data_[i] * other[i]; + return ret; + } + + constexpr Vector<T, Rows> operator*(T factor) const + { + Vector<T, Rows> ret; + for (unsigned int i = 0; i < Rows; i++) + ret[i] = data_[i] * factor; + return ret; + } + + constexpr Vector<T, Rows> operator/(T factor) const + { + Vector<T, Rows> ret; + for (unsigned int i = 0; i < Rows; i++) + ret[i] = data_[i] / factor; + return ret; + } + + constexpr double length2() const + { + double ret = 0; + for (unsigned int i = 0; i < Rows; i++) + ret += data_[i] * data_[i]; + return ret; + } + + constexpr double length() const + { + return std::sqrt(length2()); + } + +private: + std::array<T, Rows> data_; +}; + +template<typename T, unsigned int Rows, unsigned int Cols> +Vector<T, Rows> operator*(const Matrix<T, Rows, Cols> &m, const Vector<T, Cols> &v) +{ + Vector<T, Rows> result; + + for (unsigned int i = 0; i < Rows; i++) { + T sum = 0; + for (unsigned int j = 0; j < Cols; j++) + sum += m[i][j] * v[j]; + result[i] = sum; + } + + return result; +} + +template<typename T, unsigned int Rows> +bool operator==(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs) +{ + for (unsigned int i = 0; i < Rows; i++) { + if (lhs[i] != rhs[i]) + return false; + } + + return true; +} + +template<typename T, unsigned int Rows> +bool operator!=(const Vector<T, Rows> &lhs, const Vector<T, Rows> &rhs) +{ + return !(lhs == rhs); +} + +#ifndef __DOXYGEN__ +bool vectorValidateYaml(const YamlObject &obj, unsigned int size); +#endif /* __DOXYGEN__ */ + +} /* namespace ipa */ + +#ifndef __DOXYGEN__ +template<typename T, unsigned int Rows> +std::ostream &operator<<(std::ostream &out, const ipa::Vector<T, Rows> &v) +{ + out << "Vector { "; + for (unsigned int i = 0; i < Rows; i++) { + out << v[i]; + out << ((i + 1 < Rows) ? ", " : " "); + } + out << " }"; + + return out; +} + +template<typename T, unsigned int Rows> +struct YamlObject::Getter<ipa::Vector<T, Rows>> { + std::optional<ipa::Vector<T, Rows>> get(const YamlObject &obj) const + { + if (!ipa::vectorValidateYaml(obj, Rows)) + return std::nullopt; + + ipa::Vector<T, Rows> vector; + + unsigned int i = 0; + for (const YamlObject &entry : obj.asList()) { + const auto value = entry.get<T>(); + if (!value) + return std::nullopt; + vector[i++] = *value; + } + + return vector; + } +}; +#endif /* __DOXYGEN__ */ + +} /* namespace libcamera */ |