From patchwork Fri Jun 7 07:57:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 20224 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 18EDABD87C for ; Fri, 7 Jun 2024 07:57:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 935A965457; Fri, 7 Jun 2024 09:57:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="r/i4Sjo7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DC35E65455 for ; Fri, 7 Jun 2024 09:57:31 +0200 (CEST) Received: from neptunite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6147A1FA4; Fri, 7 Jun 2024 09:57:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1717747042; bh=U2RQyhXBvJJGX5A+sLaLgIhRGxzL76oN2v8JaCc5jTg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r/i4Sjo7wQv0Oc/RBTInwFDBU7hMC6wEFdEmFpTmO+HcK/cxs2jNoPwyxOpgPJ036 /+hLQk0WtFnc64ElOL2gqCkOnly66TpQ7Q+atRqxtYvwCDVjDl3GK8errId1P42e4u UlxDRdktpm1XedZLV3Db2eQ2c6E5IS1NIMhD3uJU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH v5 1/4] ipa: libipa: Add Vector class Date: Fri, 7 Jun 2024 16:57:11 +0900 Message-Id: <20240607075714.2648851-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240607075714.2648851-1-paul.elder@ideasonboard.com> References: <20240607075714.2648851-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a vector class to libipa. The original purpose of this is to replace the floating-point Point class that Raspberry Pi used in their Pwl, as that implementation of Point seemed more akin to a Vector than a Point. This is added to libipa instead of to geometry.h to avoid public API issues, plus this is not expected to be needed by applications. Signed-off-by: Paul Elder --- New in v5 --- src/ipa/libipa/vector.cpp | 162 ++++++++++++++++++++++++++++++ src/ipa/libipa/vector.h | 206 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 src/ipa/libipa/vector.cpp create mode 100644 src/ipa/libipa/vector.h diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp new file mode 100644 index 000000000..bdc3c447c --- /dev/null +++ b/src/ipa/libipa/vector.cpp @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Raspberry Pi Ltd + * Copyright (C) 2024, Paul Elder + * + * Vector and related operations + */ + +#include "vector.h" + +#include + +/** + * \file vector.h + * \brief Vector class + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Vector) + +namespace ipa { + +/** + * \class Vector + * \brief Vector class + * \tparam T Type of numerical values to be stored in the vector + * \tparam R Number of rows in the vector + */ + +/** + * \fn Vector::Vector() + * \brief Construct an identity vector + */ + +/** + * \fn Vector::Vector(const std::array &data) + * \brief Construct vector from supplied data + * \param data Data from which to construct a vector + * + * \a data is a one-dimensional vector and will be turned into a vector in + * row-major order. The size of \a data must be equal to the product of the + * number of rows and columns of the vector (RxC). + */ + +/** + * \fn Vector::readYaml + * \brief Populate the vector with yaml data + * \param yaml Yaml data to populate the vector with + * + * Any existing data in the vector will be overwritten. The size of the data + * read from \a yaml must be equal to the product of the number of rows and + * columns of the vector (RxC). + * + * The yaml data is expected to be a list with elements of type T. + * + * \return 0 on success, negative error code otherwise + */ + +/** + * \fn Vector::toString + * \brief Assemble and return a string describing the vector + * \return A string describing the vector + */ + +/** + * \fn T Vector::operator[](size_t i) const + * \brief Index to a row in the vector + * \param i Index of row to retrieve + * + * This operator[] returns a Span, which can then be indexed into again with + * another operator[], allowing a convenient m[i][j] to access elements of the + * vector. Note that the lifetime of the Span returned by this first-level + * operator[] is bound to that of the Vector itself, so it is not recommended + * to save the Span that is the result of this operator[]. + * + * \return Row \a i from the vector, as a Span + */ + +/** + * \fn T &Vector::operator[](size_t i) + * \copydoc Vector::operator[](size_t i) const + */ + +/** + * \fn Vector::x() + * \brief Convenience function to access the first element of the vector + */ + +/** + * \fn Vector::y() + * \brief Convenience function to access the second element of the vector + */ + +/** + * \fn Vector::operator-() const + * \brief Negate a Vector by negating both all of its coordinates + * \return The negated vector + */ + +/** + * \fn Vector::operator-(Vector const &other) const + * \brief Subtract one vector from another + * \param[in] other The other vector + * \return The difference of \a other from this vector + */ + +/** + * \fn Vector::operator+() + * \brief Add two vectors together + * \param[in] other The other vector + * \return The sum of the two vectors + */ + +/** + * \fn Vector::operator*(const Vector &other) const + * \brief Compute the dot product + * \param[in] other The other vector + * \return The dot product of the two vectors + */ + +/** + * \fn Vector::operator*(T factor) const + * \brief Scale up the vector + * \param[in] factor The factor + * \return The vector scaled up by \a factor + */ + +/** + * \fn Vector::operator/() + * \brief Scale down the vector + * \param[in] factor The factor + * \return The vector scaled down by \a factor + */ + +/** + * \fn Vector::len2() + * \brief Get the squared length of the vector + * \return The squared length of the vector + */ + +/** + * \fn Vector::len() + * \brief Get the length of the vector + * \return The length of the vector + */ + +/** + * \fn bool operator==(const Vector &lhs, const Vector &rhs) + * \brief Compare vectors for equality + * \return True if the two vectors are equal, false otherwise + */ + +/** + * \fn bool operator!=(const Vector &lhs, const Vector &rhs) + * \brief Compare vectors for inequality + * \return True if the two vectors are not equal, false otherwise + */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h new file mode 100644 index 000000000..87aad28b5 --- /dev/null +++ b/src/ipa/libipa/vector.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Raspberry Pi Ltd + * 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 && R >= 2> * = nullptr> +#else +template +#endif /* __DOXYGEN__ */ +class Vector +{ +public: + Vector() = default; + + Vector(const std::array &data) + { + ASSERT(data.size() == R); + + for (unsigned int i = 0; i < R; i++) + data_[i] = data[i]; + } + + ~Vector() = default; + + int readYaml(const libcamera::YamlObject &yaml) + { + if (yaml.size() != R) { + LOG(Vector, Error) + << "Wrong number of values in vector: expected " + << R << ", 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 std::string toString() const + { + std::stringstream out; + + out << "Vector { "; + for (unsigned int i = 0; i < R; i++) { + out << (*this)[i]; + out << ((i + 1 < R) ? ", " : " "); + } + out << " }"; + + return out.str(); + } + + const T operator[](size_t i) const + { + return data_[i]; + } + + T &operator[](size_t i) + { + return data_[i]; + } + + const T x() const + { + return data_[0]; + } + + const T y() const + { + return data_[1]; + } + + constexpr Vector operator-() const + { + Vector ret; + for (unsigned int i = 0; i < R; i++) + ret[i] = -data_[i]; + return ret; + } + + constexpr Vector operator-(const Vector &other) const + { + Vector ret; + for (unsigned int i = 0; i < R; i++) + ret[i] = data_[i] - other[i]; + return ret; + } + + constexpr Vector operator+(const Vector &other) const + { + Vector ret; + for (unsigned int i = 0; i < R; 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 < R; i++) + ret += data_[i] * other[i]; + return ret; + } + + constexpr Vector operator*(T factor) const + { + Vector ret; + for (unsigned int i = 0; i < R; i++) + ret[i] = data_[i] * factor; + return ret; + } + + constexpr Vector operator/(T factor) const + { + Vector ret; + for (unsigned int i = 0; i < R; i++) + ret[i] = data_[i] / factor; + return ret; + } + + constexpr T len2() const + { + T ret = 0; + for (unsigned int i = 0; i < R; i++) + ret += data_[i] * data_[i]; + return ret; + } + + constexpr double len() const + { + return std::sqrt(len2()); + } + +private: + std::array data_; +}; + +#ifndef __DOXYGEN__ +template> * = nullptr> +#endif /* __DOXYGEN__ */ +bool operator==(const Vector &lhs, const Vector &rhs) +{ + for (unsigned int i = 0; i < R; i++) + if (lhs[i] != rhs[i]) + return false; + + return true; +} + +#ifndef __DOXYGEN__ +template> * = nullptr> +#endif /* __DOXYGEN__ */ +bool operator!=(const Vector &lhs, const Vector &rhs) +{ + for (unsigned int i = 0; i < R; i++) + if (lhs[i] != rhs[i]) + return true; + + return false; +} + +} /* namespace ipa */ + +#ifndef __DOXYGEN__ +template +std::ostream &operator<<(std::ostream &out, const ipa::Vector &v) +{ + out << v.toString(); + return out; +} +#endif /* __DOXYGEN__ */ + +} /* namespace libcamera */