/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2024, Paul Elder * * Vector and related operations */ #pragma once #include #include #include #include #include #include #include "libcamera/internal/yaml_parser.h" namespace libcamera { LOG_DECLARE_CATEGORY(Vector) namespace ipa { #ifndef __DOXYGEN__ template> * = nullptr> #else template #endif /* __DOXYGEN__ */ class Vector { public: constexpr Vector() = default; constexpr Vector(const std::array &data) { for (unsigned int i = 0; i < Rows; i++) data_[i] = data[i]; } int readYaml(const libcamera::YamlObject &yaml) { if (yaml.size() != Rows) { LOG(Vector, Error) << "Wrong number of values in vector: expected " << Rows << ", got " << yaml.size(); return -EINVAL; } unsigned int i = 0; for (const auto &x : yaml.asList()) { auto value = x.get(); if (!value) { LOG(Vector, Error) << "Failed to read vector value"; return -EINVAL; } data_[i++] = *value; } return 0; } 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= 1>> #endif /* __DOXYGEN__ */ constexpr T x() const { return data_[0]; } #ifndef __DOXYGEN__ template= 2>> #endif /* __DOXYGEN__ */ constexpr T y() const { return data_[1]; } #ifndef __DOXYGEN__ template= 3>> #endif /* __DOXYGEN__ */ constexpr T z() const { return data_[2]; } constexpr Vector operator-() const { Vector ret; for (unsigned int i = 0; i < Rows; i++) ret[i] = -data_[i]; return ret; } constexpr Vector operator-(const Vector &other) const { Vector ret; for (unsigned int i = 0; i < Rows; i++) ret[i] = data_[i] - other[i]; return ret; } constexpr Vector operator+(const Vector &other) const { Vector ret; for (unsigned int i = 0; i < Rows; i++) ret[i] = data_[i] + other[i]; return ret; } constexpr T operator*(const Vector &other) const { T ret = 0; for (unsigned int i = 0; i < Rows; i++) ret += data_[i] * other[i]; return ret; } constexpr Vector operator*(T factor) const { Vector ret; for (unsigned int i = 0; i < Rows; i++) ret[i] = data_[i] * factor; return ret; } constexpr Vector operator/(T factor) const { Vector 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 data_; }; template bool operator==(const Vector &lhs, const Vector &rhs) { for (unsigned int i = 0; i < Rows; i++) { if (lhs[i] != rhs[i]) return false; } return true; } template bool operator!=(const Vector &lhs, const Vector &rhs) { return !(lhs == rhs); } #ifndef __DOXYGEN__ bool vectorValidateYaml(const YamlObject &obj, unsigned int size); #endif /* __DOXYGEN__ */ } /* namespace ipa */ #ifndef __DOXYGEN__ template std::ostream &operator<<(std::ostream &out, const ipa::Vector &v) { out << "Vector { "; for (unsigned int i = 0; i < Rows; i++) { out << v[i]; out << ((i + 1 < Rows) ? ", " : " "); } out << " }"; return out; } template struct YamlObject::Getter> { std::optional> get(const YamlObject &obj) const { if (!ipa::vectorValidateYaml(obj, Rows)) return std::nullopt; ipa::Vector vector; unsigned int i = 0; for (const YamlObject &entry : obj.asList()) { const auto value = entry.get(); if (!value) return std::nullopt; vector[i++] = *value; } return vector; } }; #endif /* __DOXYGEN__ */ } /* namespace libcamera */