From patchwork Thu Feb 6 14:10:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22742 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 7427EC32EA for ; Thu, 6 Feb 2025 14:10:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 27436685EA; Thu, 6 Feb 2025 15:10:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="aEhB+sBr"; 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 957096053F for ; Thu, 6 Feb 2025 15:10:25 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6b7d:6f52:efbb:46c8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0AD2C1193; Thu, 6 Feb 2025 15:09:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1738850952; bh=0jBImBCpJQ48gSW+zJuQBQ57Qc398QkP5SOiIhEoUMc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aEhB+sBru6rrBlPpcyCPb7gx/NxX6MiH9/WEVbiEDkvW3FaBLMmmHulbWUVuNZTpC NL+y+lebDOBTdMyUwKPeeuk0SROI8AuywsfJ4wbnogbdQdMch8GWKhPEOkfdY6YeDp Mj0Y0fi+UIBCWwt8Sw0KYM+kVVJjnch2dGuPaHeM= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 1/4] libcamera: Copy Vector class files from libipa Date: Thu, 6 Feb 2025 15:10:08 +0100 Message-ID: <20250206141018.236272-2-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206141018.236272-1-stefan.klug@ideasonboard.com> References: <20250206141018.236272-1-stefan.klug@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" Prepare the move of the Vector class from libipa to libcamera by copying the relevant files into the corresponding libcamera directories. The files are copied without modification. Signed-off-by: Stefan Klug Acked-by: Kieran Bingham --- include/libcamera/internal/vector.h | 370 ++++++++++++++++++++++++++++ src/libcamera/vector.cpp | 351 ++++++++++++++++++++++++++ test/vector.cpp | 100 ++++++++ 3 files changed, 821 insertions(+) create mode 100644 include/libcamera/internal/vector.h create mode 100644 src/libcamera/vector.cpp create mode 100644 test/vector.cpp diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h new file mode 100644 index 000000000000..fe33c9d6fbd1 --- /dev/null +++ b/include/libcamera/internal/vector.h @@ -0,0 +1,370 @@ +/* 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 + +#include +#include + +#include "libcamera/internal/matrix.h" +#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 explicit Vector(T scalar) + { + data_.fill(scalar); + } + + constexpr Vector(const std::array &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]; + } + + 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 + { + return apply(*this, other, std::plus<>{}); + } + + constexpr Vector operator+(T scalar) const + { + return apply(*this, scalar, std::plus<>{}); + } + + constexpr Vector operator-(const Vector &other) const + { + return apply(*this, other, std::minus<>{}); + } + + constexpr Vector operator-(T scalar) const + { + return apply(*this, scalar, std::minus<>{}); + } + + constexpr Vector operator*(const Vector &other) const + { + return apply(*this, other, std::multiplies<>{}); + } + + constexpr Vector operator*(T scalar) const + { + return apply(*this, scalar, std::multiplies<>{}); + } + + constexpr Vector operator/(const Vector &other) const + { + return apply(*this, other, std::divides<>{}); + } + + constexpr Vector operator/(T scalar) const + { + return apply(*this, scalar, std::divides<>{}); + } + + Vector &operator+=(const Vector &other) + { + return apply(other, [](T a, T b) { return a + b; }); + } + + Vector &operator+=(T scalar) + { + return apply(scalar, [](T a, T b) { return a + b; }); + } + + Vector &operator-=(const Vector &other) + { + return apply(other, [](T a, T b) { return a - b; }); + } + + Vector &operator-=(T scalar) + { + return apply(scalar, [](T a, T b) { return a - b; }); + } + + Vector &operator*=(const Vector &other) + { + return apply(other, [](T a, T b) { return a * b; }); + } + + Vector &operator*=(T scalar) + { + return apply(scalar, [](T a, T b) { return a * b; }); + } + + Vector &operator/=(const Vector &other) + { + return apply(other, [](T a, T b) { return a / b; }); + } + + Vector &operator/=(T scalar) + { + return apply(scalar, [](T a, T b) { return a / b; }); + } + + constexpr Vector min(const Vector &other) const + { + return apply(*this, other, [](T a, T b) { return std::min(a, b); }); + } + + constexpr Vector min(T scalar) const + { + return apply(*this, scalar, [](T a, T b) { return std::min(a, b); }); + } + + constexpr Vector max(const Vector &other) const + { + return apply(*this, other, [](T a, T b) { return std::max(a, b); }); + } + + constexpr Vector max(T scalar) const + { + return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); }); + } + + constexpr T dot(const Vector &other) const + { + T ret = 0; + for (unsigned int i = 0; i < Rows; i++) + ret += data_[i] * other[i]; + return ret; + } + +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr const T &x() const { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr const T &y() const { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr const T &z() const { return data_[2]; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr T &x() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr T &y() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr T &z() { return data_[2]; } + +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr const T &r() const { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr const T &g() const { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr const T &b() const { return data_[2]; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr T &r() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr T &g() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr T &b() { return data_[2]; } + + 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()); + } + + template + constexpr R sum() const + { + return std::accumulate(data_.begin(), data_.end(), R{}); + } + +private: + template + static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + rhs.data_.begin(), result.data_.begin(), + op); + + return result; + } + + template + static constexpr Vector apply(const Vector &lhs, T rhs, BinaryOp op) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + result.data_.begin(), + [&op, rhs](T v) { return op(v, rhs); }); + + return result; + } + + template + Vector &apply(const Vector &other, BinaryOp op) + { + auto itOther = other.data_.begin(); + std::for_each(data_.begin(), data_.end(), + [&op, &itOther](T &v) { v = op(v, *itOther++); }); + + return *this; + } + + template + Vector &apply(T scalar, BinaryOp op) + { + std::for_each(data_.begin(), data_.end(), + [&op, scalar](T &v) { v = op(v, scalar); }); + + return *this; + } + + std::array data_; +}; + +template +using RGB = Vector; + +template +Vector operator*(const Matrix &m, const Vector &v) +{ + Vector 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 +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 */ diff --git a/src/libcamera/vector.cpp b/src/libcamera/vector.cpp new file mode 100644 index 000000000000..8019f8cfdc85 --- /dev/null +++ b/src/libcamera/vector.cpp @@ -0,0 +1,351 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * 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 Rows Number of dimension of the vector (= number of elements) + */ + +/** + * \fn Vector::Vector() + * \brief Construct an uninitialized vector + */ + +/** + * \fn Vector::Vector(T scalar) + * \brief Construct a vector filled with a \a scalar value + * \param[in] scalar The scalar value + */ + +/** + * \fn Vector::Vector(const std::array &data) + * \brief Construct vector from supplied data + * \param data Data from which to construct a vector + * + * The size of \a data must be equal to the dimension size Rows of the vector. + */ + +/** + * \fn T Vector::operator[](size_t i) const + * \brief Index to an element in the vector + * \param i Index of element to retrieve + * \return Element at index \a i from the vector + */ + +/** + * \fn T &Vector::operator[](size_t i) + * \copydoc Vector::operator[](size_t i) const + */ + +/** + * \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 Calculate the sum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise sum of this vector and \a other + */ + +/** + * \fn Vector::operator+(T scalar) const + * \brief Calculate the sum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise sum of this vector and \a other + */ + +/** + * \fn Vector::operator-(Vector const &other) const + * \brief Calculate the difference of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise subtraction of \a other from this vector + */ + +/** + * \fn Vector::operator-(T scalar) const + * \brief Calculate the difference of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise subtraction of \a scalar from this vector + */ + +/** + * \fn Vector::operator*(const Vector &other) const + * \brief Calculate the product of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise product of this vector and \a other + */ + +/** + * \fn Vector::operator*(T scalar) const + * \brief Calculate the product of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise product of this vector and \a scalar + */ + +/** + * \fn Vector::operator/(const Vector &other) const + * \brief Calculate the quotient of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise division of this vector by \a other + */ + +/** + * \fn Vector::operator/(T scalar) const + * \brief Calculate the quotient of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise division of this vector by \a scalar + */ + +/** + * \fn Vector::operator+=(Vector const &other) + * \brief Add \a other element-wise to this vector + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator+=(T scalar) + * \brief Add \a scalar element-wise to this vector + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator-=(Vector const &other) + * \brief Subtract \a other element-wise from this vector + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator-=(T scalar) + * \brief Subtract \a scalar element-wise from this vector + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator*=(const Vector &other) + * \brief Multiply this vector by \a other element-wise + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator*=(T scalar) + * \brief Multiply this vector by \a scalar element-wise + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator/=(const Vector &other) + * \brief Divide this vector by \a other element-wise + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator/=(T scalar) + * \brief Divide this vector by \a scalar element-wise + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::min(const Vector &other) const + * \brief Calculate the minimum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise minimum of this vector and \a other + */ + +/** + * \fn Vector::min(T scalar) const + * \brief Calculate the minimum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise minimum of this vector and \a scalar + */ + +/** + * \fn Vector::max(const Vector &other) const + * \brief Calculate the maximum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise maximum of this vector and \a other + */ + +/** + * \fn Vector::max(T scalar) const + * \brief Calculate the maximum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise maximum of this vector and \a scalar + */ + +/** + * \fn Vector::dot(const Vector &other) const + * \brief Compute the dot product + * \param[in] other The other vector + * \return The dot product of the two vectors + */ + +/** + * \fn constexpr T &Vector::x() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn constexpr T &Vector::y() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn constexpr T &Vector::z() + * \brief Convenience function to access the third element of the vector + * \return The third element of the vector + */ + +/** + * \fn constexpr const T &Vector::x() const + * \copydoc Vector::x() + */ + +/** + * \fn constexpr const T &Vector::y() const + * \copydoc Vector::y() + */ + +/** + * \fn constexpr const T &Vector::z() const + * \copydoc Vector::z() + */ + +/** + * \fn constexpr T &Vector::r() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn constexpr T &Vector::g() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn constexpr T &Vector::b() + * \brief Convenience function to access the third element of the vector + * \return The third element of the vector + */ + +/** + * \fn constexpr const T &Vector::r() const + * \copydoc Vector::r() + */ + +/** + * \fn constexpr const T &Vector::g() const + * \copydoc Vector::g() + */ + +/** + * \fn constexpr const T &Vector::b() const + * \copydoc Vector::b() + */ + +/** + * \fn Vector::length2() + * \brief Get the squared length of the vector + * \return The squared length of the vector + */ + +/** + * \fn Vector::length() + * \brief Get the length of the vector + * \return The length of the vector + */ + +/** + * \fn Vector::sum() const + * \brief Calculate the sum of all the vector elements + * \tparam R The type of the sum + * + * The type R of the sum defaults to the type T of the elements, but can be set + * explicitly to use a different type in case the type T would risk + * overflowing. + * + * \return The sum of all the vector elements + */ + +/** + * \fn Vector operator*(const Matrix &m, const Vector &v) + * \brief Multiply a matrix by a vector + * \tparam T Numerical type of the contents of the matrix and vector + * \tparam Rows The number of rows in the matrix + * \tparam Cols The number of columns in the matrix (= rows in the vector) + * \param m The matrix + * \param v The vector + * \return Product of matrix \a m and vector \a v + */ + +/** + * \typedef RGB + * \brief A Vector of 3 elements representing an RGB pixel value + */ + +/** + * \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 + */ + +#ifndef __DOXYGEN__ +bool vectorValidateYaml(const YamlObject &obj, unsigned int size) +{ + if (!obj.isList()) + return false; + + if (obj.size() != size) { + LOG(Vector, Error) + << "Wrong number of values in YAML vector: expected " + << size << ", got " << obj.size(); + return false; + } + + return true; +} +#endif /* __DOXYGEN__ */ + +} /* namespace ipa */ + +} /* namespace libcamera */ diff --git a/test/vector.cpp b/test/vector.cpp new file mode 100644 index 000000000000..8e4ec77d7820 --- /dev/null +++ b/test/vector.cpp @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * Vector tests + */ + +#include "../src/ipa/libipa/vector.h" + +#include +#include + +#include "test.h" + +using namespace libcamera::ipa; + +#define ASSERT_EQ(a, b) \ +if ((a) != (b)) { \ + std::cout << #a " != " #b << " (line " << __LINE__ << ")" \ + << std::endl; \ + return TestFail; \ +} + +class VectorTest : public Test +{ +protected: + int run() + { + Vector v1{ 0.0 }; + + ASSERT_EQ(v1[0], 0.0); + ASSERT_EQ(v1[1], 0.0); + ASSERT_EQ(v1[2], 0.0); + + ASSERT_EQ(v1.length(), 0.0); + ASSERT_EQ(v1.length2(), 0.0); + + Vector v2{{ 1.0, 4.0, 8.0 }}; + + ASSERT_EQ(v2[0], 1.0); + ASSERT_EQ(v2[1], 4.0); + ASSERT_EQ(v2[2], 8.0); + + ASSERT_EQ(v2.x(), 1.0); + ASSERT_EQ(v2.y(), 4.0); + ASSERT_EQ(v2.z(), 8.0); + + ASSERT_EQ(v2.r(), 1.0); + ASSERT_EQ(v2.g(), 4.0); + ASSERT_EQ(v2.b(), 8.0); + + ASSERT_EQ(v2.length2(), 81.0); + ASSERT_EQ(v2.length(), 9.0); + ASSERT_EQ(v2.sum(), 13.0); + + Vector v3{ v2 }; + + ASSERT_EQ(v2, v3); + + v3 = Vector{{ 4.0, 4.0, 4.0 }}; + + ASSERT_EQ(v2 + v3, (Vector{{ 5.0, 8.0, 12.0 }})); + ASSERT_EQ(v2 + 4.0, (Vector{{ 5.0, 8.0, 12.0 }})); + ASSERT_EQ(v2 - v3, (Vector{{ -3.0, 0.0, 4.0 }})); + ASSERT_EQ(v2 - 4.0, (Vector{{ -3.0, 0.0, 4.0 }})); + ASSERT_EQ(v2 * v3, (Vector{{ 4.0, 16.0, 32.0 }})); + ASSERT_EQ(v2 * 4.0, (Vector{{ 4.0, 16.0, 32.0 }})); + ASSERT_EQ(v2 / v3, (Vector{{ 0.25, 1.0, 2.0 }})); + ASSERT_EQ(v2 / 4.0, (Vector{{ 0.25, 1.0, 2.0 }})); + + ASSERT_EQ(v2.min(v3), (Vector{{ 1.0, 4.0, 4.0 }})); + ASSERT_EQ(v2.min(4.0), (Vector{{ 1.0, 4.0, 4.0 }})); + ASSERT_EQ(v2.max(v3), (Vector{{ 4.0, 4.0, 8.0 }})); + ASSERT_EQ(v2.max(4.0), (Vector{{ 4.0, 4.0, 8.0 }})); + + ASSERT_EQ(v2.dot(v3), 52.0); + + v2 += v3; + ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); + v2 -= v3; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + v2 *= v3; + ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); + v2 /= v3; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + + v2 += 4.0; + ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); + v2 -= 4.0; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + v2 *= 4.0; + ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); + v2 /= 4.0; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + + return TestPass; + } +}; + +TEST_REGISTER(VectorTest) From patchwork Thu Feb 6 14:10:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22743 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 827D6C32EA for ; Thu, 6 Feb 2025 14:10:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 301DD685EA; Thu, 6 Feb 2025 15:10:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="noLBplBo"; 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 21AA2685E9 for ; Thu, 6 Feb 2025 15:10:28 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6b7d:6f52:efbb:46c8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8CEBF1193; Thu, 6 Feb 2025 15:09:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1738850954; bh=+FW104UwTZQHeTfkauhTqhUeQSQHwC3w8z/tDG1PYYk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=noLBplBoEIU4GTigrYZPLo6a4SVCdLqEuaRt7XQzRNWY+6lL0B/u5Mtf8i4157nlP CbBxxUesRXjg9ljOuet9G0nsGn84G0dHhrHneGHlbQ4WWPYCeYUzZZkJOD/EL+Pq8C D5Ye4oFOqijIXW/rU4Z8Y6uWnJwsl3fMtHS4kXXk= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 2/4] libcamera: Adapt Vector class to new location Date: Thu, 6 Feb 2025 15:10:09 +0100 Message-ID: <20250206141018.236272-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206141018.236272-1-stefan.klug@ideasonboard.com> References: <20250206141018.236272-1-stefan.klug@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" Change the namespace of the Vector class from libipa to libcamera and add it to the build. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham --- include/libcamera/internal/meson.build | 1 + include/libcamera/internal/vector.h | 14 +++++--------- src/libcamera/meson.build | 1 + src/libcamera/vector.cpp | 6 +----- test/meson.build | 1 + test/vector.cpp | 4 ++-- 6 files changed, 11 insertions(+), 16 deletions(-) diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 7d6aa8b72bd7..45408b313848 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -43,6 +43,7 @@ libcamera_internal_headers = files([ 'v4l2_pixelformat.h', 'v4l2_subdevice.h', 'v4l2_videodevice.h', + 'vector.h', 'yaml_parser.h', ]) diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h index fe33c9d6fbd1..a67a09474204 100644 --- a/include/libcamera/internal/vector.h +++ b/include/libcamera/internal/vector.h @@ -24,8 +24,6 @@ namespace libcamera { LOG_DECLARE_CATEGORY(Vector) -namespace ipa { - #ifndef __DOXYGEN__ template> * = nullptr> @@ -329,11 +327,9 @@ bool operator!=(const Vector &lhs, const Vector &rhs) 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) +std::ostream &operator<<(std::ostream &out, const Vector &v) { out << "Vector { "; for (unsigned int i = 0; i < Rows; i++) { @@ -346,13 +342,13 @@ std::ostream &operator<<(std::ostream &out, const ipa::Vector &v) } template -struct YamlObject::Getter> { - std::optional> get(const YamlObject &obj) const +struct YamlObject::Getter> { + std::optional> get(const YamlObject &obj) const { - if (!ipa::vectorValidateYaml(obj, Rows)) + if (!vectorValidateYaml(obj, Rows)) return std::nullopt; - ipa::Vector vector; + Vector vector; unsigned int i = 0; for (const YamlObject &entry : obj.asList()) { diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 57fde8a8fab0..de22b8e60dde 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -53,6 +53,7 @@ libcamera_internal_sources = files([ 'v4l2_pixelformat.cpp', 'v4l2_subdevice.cpp', 'v4l2_videodevice.cpp', + 'vector.cpp', 'yaml_parser.cpp', ]) diff --git a/src/libcamera/vector.cpp b/src/libcamera/vector.cpp index 8019f8cfdc85..85ca2208245a 100644 --- a/src/libcamera/vector.cpp +++ b/src/libcamera/vector.cpp @@ -5,7 +5,7 @@ * Vector and related operations */ -#include "vector.h" +#include "libcamera/internal/vector.h" #include @@ -18,8 +18,6 @@ namespace libcamera { LOG_DEFINE_CATEGORY(Vector) -namespace ipa { - /** * \class Vector * \brief Vector class @@ -346,6 +344,4 @@ bool vectorValidateYaml(const YamlObject &obj, unsigned int size) } #endif /* __DOXYGEN__ */ -} /* namespace ipa */ - } /* namespace libcamera */ diff --git a/test/meson.build b/test/meson.build index 5ed052ed62c8..4095664994fd 100644 --- a/test/meson.build +++ b/test/meson.build @@ -73,6 +73,7 @@ internal_tests = [ {'name': 'timer-thread', 'sources': ['timer-thread.cpp']}, {'name': 'unique-fd', 'sources': ['unique-fd.cpp']}, {'name': 'utils', 'sources': ['utils.cpp']}, + {'name': 'vector', 'sources': ['vector.cpp']}, {'name': 'yaml-parser', 'sources': ['yaml-parser.cpp']}, ] diff --git a/test/vector.cpp b/test/vector.cpp index 8e4ec77d7820..4fae960defc1 100644 --- a/test/vector.cpp +++ b/test/vector.cpp @@ -5,14 +5,14 @@ * Vector tests */ -#include "../src/ipa/libipa/vector.h" +#include "libcamera/internal/vector.h" #include #include #include "test.h" -using namespace libcamera::ipa; +using namespace libcamera; #define ASSERT_EQ(a, b) \ if ((a) != (b)) { \ From patchwork Thu Feb 6 14:10:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22744 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 8E3EBC32EA for ; Thu, 6 Feb 2025 14:10:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 13C8C685F3; Thu, 6 Feb 2025 15:10:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="c1nqBfVH"; 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 F0978685E2 for ; Thu, 6 Feb 2025 15:10:30 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6b7d:6f52:efbb:46c8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 722A011DA; Thu, 6 Feb 2025 15:09:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1738850957; bh=70TC5rfQAKHjA1/Nsb/TBHDPn/n+dEWmX4/6XL1jX6w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c1nqBfVHem8pO7Hu8Nez4AdFWORjicsRPLz3u3NCcJS7uZ7Sl+IMAtXYJA6RADF3u 4Dj3VDonzapjBQsYdz2VTDMO/NAWNmDOjuGmy+ofC16m8YUHLiM+1B0Lo/e2+NwY34 D7mlfIyYuQsWh8tbZsV4bRo6deE3vQZhe6GLqoXo= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 3/4] ipa: Use Vector class from libcamera Date: Thu, 6 Feb 2025 15:10:10 +0100 Message-ID: <20250206141018.236272-4-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206141018.236272-1-stefan.klug@ideasonboard.com> References: <20250206141018.236272-1-stefan.klug@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" Now that there is a Vector class in libcamera, use that one. Signed-off-by: Stefan Klug Reviewed-by: Kieran Bingham Reviewed-by: Naushir Patuck --- src/ipa/ipu3/algorithms/awb.h | 2 +- src/ipa/libipa/colours.h | 2 +- src/ipa/libipa/pwl.h | 2 +- src/ipa/rkisp1/algorithms/awb.h | 3 ++- src/ipa/rkisp1/ipa_context.h | 2 +- src/ipa/rpi/controller/rpi/agc_channel.cpp | 7 ++++--- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index 1916990a5364..dbf69c9073a1 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -13,7 +13,7 @@ #include -#include "libipa/vector.h" +#include "libcamera/internal/vector.h" #include "algorithm.h" diff --git a/src/ipa/libipa/colours.h b/src/ipa/libipa/colours.h index fa6a8b575cc7..d39b2ca8b87e 100644 --- a/src/ipa/libipa/colours.h +++ b/src/ipa/libipa/colours.h @@ -9,7 +9,7 @@ #include -#include "vector.h" +#include "libcamera/internal/vector.h" namespace libcamera { diff --git a/src/ipa/libipa/pwl.h b/src/ipa/libipa/pwl.h index d4ec9f4f18fb..8fdc70538b93 100644 --- a/src/ipa/libipa/pwl.h +++ b/src/ipa/libipa/pwl.h @@ -12,7 +12,7 @@ #include #include -#include "vector.h" +#include "libcamera/internal/vector.h" namespace libcamera { diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h index e424804861a6..34ec42cbb164 100644 --- a/src/ipa/rkisp1/algorithms/awb.h +++ b/src/ipa/rkisp1/algorithms/awb.h @@ -9,8 +9,9 @@ #include +#include "libcamera/internal/vector.h" + #include "libipa/interpolator.h" -#include "libipa/vector.h" #include "algorithm.h" diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 5d5b79fa615e..c765b928a55f 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -22,10 +22,10 @@ #include "libcamera/internal/debug_controls.h" #include "libcamera/internal/matrix.h" +#include "libcamera/internal/vector.h" #include #include -#include namespace libcamera { diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp index e79184b7ac74..a5562760e034 100644 --- a/src/ipa/rpi/controller/rpi/agc_channel.cpp +++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp @@ -12,8 +12,9 @@ #include +#include "libcamera/internal/vector.h" + #include "libipa/colours.h" -#include "libipa/vector.h" #include "../awb_status.h" #include "../device_status.h" @@ -700,7 +701,7 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, * Note that the weights are applied by the IPA to the statistics directly, * before they are given to us here. */ - ipa::RGB sum{ 0.0 }; + RGB sum{ 0.0 }; double pixelSum = 0; for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { auto ®ion = stats->agcRegions.get(i); @@ -716,7 +717,7 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, /* Factor in the AWB correction if needed. */ if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) - sum *= ipa::RGB{{ awb.gainR, awb.gainR, awb.gainB }}; + sum *= RGB{ { awb.gainR, awb.gainR, awb.gainB } }; double ySum = ipa::rec601LuminanceFromRGB(sum); From patchwork Thu Feb 6 14:10:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22745 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 6D112C32EA for ; Thu, 6 Feb 2025 14:10:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 24431685F4; Thu, 6 Feb 2025 15:10:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DWtJkdZt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5B751685F5 for ; Thu, 6 Feb 2025 15:10:33 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:6b7d:6f52:efbb:46c8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B9BA111DA; Thu, 6 Feb 2025 15:09:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1738850959; bh=3EVGZqQezmxG2hfR8jIBWg30aoMYlNb/GRMOuZkyIyI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DWtJkdZt8QLdUj3sHiC8IxBVgu3IjvR6QaOtsmfETJVFsTSYyptoDGos1ZAT/NAnU khI6CbSM8WRE7qIFYLX08yOMvJ78MjdwcVGTKWcBAYljlvmetSm7EMLh87grGzX2Oc tQA4FrnY4eqDDDR8Ax/etIBOkfY69smWL559i4mY= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 4/4] libipa: Drop Vector class Date: Thu, 6 Feb 2025 15:10:11 +0100 Message-ID: <20250206141018.236272-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250206141018.236272-1-stefan.klug@ideasonboard.com> References: <20250206141018.236272-1-stefan.klug@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" The Vector class from libipa is not used anymore. Drop it. Signed-off-by: Stefan Klug Acked-by: Kieran Bingham --- src/ipa/libipa/meson.build | 2 - src/ipa/libipa/vector.cpp | 351 ---------------------------------- src/ipa/libipa/vector.h | 370 ------------------------------------ test/ipa/libipa/meson.build | 1 - test/ipa/libipa/vector.cpp | 100 ---------- 5 files changed, 824 deletions(-) delete mode 100644 src/ipa/libipa/vector.cpp delete mode 100644 src/ipa/libipa/vector.h delete mode 100644 test/ipa/libipa/vector.cpp diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build index f2b2f4be50db..12d8d15bf52a 100644 --- a/src/ipa/libipa/meson.build +++ b/src/ipa/libipa/meson.build @@ -14,7 +14,6 @@ libipa_headers = files([ 'lux.h', 'module.h', 'pwl.h', - 'vector.h', ]) libipa_sources = files([ @@ -31,7 +30,6 @@ libipa_sources = files([ 'lux.cpp', 'module.cpp', 'pwl.cpp', - 'vector.cpp', ]) libipa_includes = include_directories('..') diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp deleted file mode 100644 index 8019f8cfdc85..000000000000 --- a/src/ipa/libipa/vector.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * 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 Rows Number of dimension of the vector (= number of elements) - */ - -/** - * \fn Vector::Vector() - * \brief Construct an uninitialized vector - */ - -/** - * \fn Vector::Vector(T scalar) - * \brief Construct a vector filled with a \a scalar value - * \param[in] scalar The scalar value - */ - -/** - * \fn Vector::Vector(const std::array &data) - * \brief Construct vector from supplied data - * \param data Data from which to construct a vector - * - * The size of \a data must be equal to the dimension size Rows of the vector. - */ - -/** - * \fn T Vector::operator[](size_t i) const - * \brief Index to an element in the vector - * \param i Index of element to retrieve - * \return Element at index \a i from the vector - */ - -/** - * \fn T &Vector::operator[](size_t i) - * \copydoc Vector::operator[](size_t i) const - */ - -/** - * \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 Calculate the sum of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise sum of this vector and \a other - */ - -/** - * \fn Vector::operator+(T scalar) const - * \brief Calculate the sum of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise sum of this vector and \a other - */ - -/** - * \fn Vector::operator-(Vector const &other) const - * \brief Calculate the difference of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise subtraction of \a other from this vector - */ - -/** - * \fn Vector::operator-(T scalar) const - * \brief Calculate the difference of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise subtraction of \a scalar from this vector - */ - -/** - * \fn Vector::operator*(const Vector &other) const - * \brief Calculate the product of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise product of this vector and \a other - */ - -/** - * \fn Vector::operator*(T scalar) const - * \brief Calculate the product of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise product of this vector and \a scalar - */ - -/** - * \fn Vector::operator/(const Vector &other) const - * \brief Calculate the quotient of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise division of this vector by \a other - */ - -/** - * \fn Vector::operator/(T scalar) const - * \brief Calculate the quotient of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise division of this vector by \a scalar - */ - -/** - * \fn Vector::operator+=(Vector const &other) - * \brief Add \a other element-wise to this vector - * \param[in] other The other vector - * \return This vector - */ - -/** - * \fn Vector::operator+=(T scalar) - * \brief Add \a scalar element-wise to this vector - * \param[in] scalar The scalar - * \return This vector - */ - -/** - * \fn Vector::operator-=(Vector const &other) - * \brief Subtract \a other element-wise from this vector - * \param[in] other The other vector - * \return This vector - */ - -/** - * \fn Vector::operator-=(T scalar) - * \brief Subtract \a scalar element-wise from this vector - * \param[in] scalar The scalar - * \return This vector - */ - -/** - * \fn Vector::operator*=(const Vector &other) - * \brief Multiply this vector by \a other element-wise - * \param[in] other The other vector - * \return This vector - */ - -/** - * \fn Vector::operator*=(T scalar) - * \brief Multiply this vector by \a scalar element-wise - * \param[in] scalar The scalar - * \return This vector - */ - -/** - * \fn Vector::operator/=(const Vector &other) - * \brief Divide this vector by \a other element-wise - * \param[in] other The other vector - * \return This vector - */ - -/** - * \fn Vector::operator/=(T scalar) - * \brief Divide this vector by \a scalar element-wise - * \param[in] scalar The scalar - * \return This vector - */ - -/** - * \fn Vector::min(const Vector &other) const - * \brief Calculate the minimum of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise minimum of this vector and \a other - */ - -/** - * \fn Vector::min(T scalar) const - * \brief Calculate the minimum of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise minimum of this vector and \a scalar - */ - -/** - * \fn Vector::max(const Vector &other) const - * \brief Calculate the maximum of this vector and \a other element-wise - * \param[in] other The other vector - * \return The element-wise maximum of this vector and \a other - */ - -/** - * \fn Vector::max(T scalar) const - * \brief Calculate the maximum of this vector and \a scalar element-wise - * \param[in] scalar The scalar - * \return The element-wise maximum of this vector and \a scalar - */ - -/** - * \fn Vector::dot(const Vector &other) const - * \brief Compute the dot product - * \param[in] other The other vector - * \return The dot product of the two vectors - */ - -/** - * \fn constexpr T &Vector::x() - * \brief Convenience function to access the first element of the vector - * \return The first element of the vector - */ - -/** - * \fn constexpr T &Vector::y() - * \brief Convenience function to access the second element of the vector - * \return The second element of the vector - */ - -/** - * \fn constexpr T &Vector::z() - * \brief Convenience function to access the third element of the vector - * \return The third element of the vector - */ - -/** - * \fn constexpr const T &Vector::x() const - * \copydoc Vector::x() - */ - -/** - * \fn constexpr const T &Vector::y() const - * \copydoc Vector::y() - */ - -/** - * \fn constexpr const T &Vector::z() const - * \copydoc Vector::z() - */ - -/** - * \fn constexpr T &Vector::r() - * \brief Convenience function to access the first element of the vector - * \return The first element of the vector - */ - -/** - * \fn constexpr T &Vector::g() - * \brief Convenience function to access the second element of the vector - * \return The second element of the vector - */ - -/** - * \fn constexpr T &Vector::b() - * \brief Convenience function to access the third element of the vector - * \return The third element of the vector - */ - -/** - * \fn constexpr const T &Vector::r() const - * \copydoc Vector::r() - */ - -/** - * \fn constexpr const T &Vector::g() const - * \copydoc Vector::g() - */ - -/** - * \fn constexpr const T &Vector::b() const - * \copydoc Vector::b() - */ - -/** - * \fn Vector::length2() - * \brief Get the squared length of the vector - * \return The squared length of the vector - */ - -/** - * \fn Vector::length() - * \brief Get the length of the vector - * \return The length of the vector - */ - -/** - * \fn Vector::sum() const - * \brief Calculate the sum of all the vector elements - * \tparam R The type of the sum - * - * The type R of the sum defaults to the type T of the elements, but can be set - * explicitly to use a different type in case the type T would risk - * overflowing. - * - * \return The sum of all the vector elements - */ - -/** - * \fn Vector operator*(const Matrix &m, const Vector &v) - * \brief Multiply a matrix by a vector - * \tparam T Numerical type of the contents of the matrix and vector - * \tparam Rows The number of rows in the matrix - * \tparam Cols The number of columns in the matrix (= rows in the vector) - * \param m The matrix - * \param v The vector - * \return Product of matrix \a m and vector \a v - */ - -/** - * \typedef RGB - * \brief A Vector of 3 elements representing an RGB pixel value - */ - -/** - * \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 - */ - -#ifndef __DOXYGEN__ -bool vectorValidateYaml(const YamlObject &obj, unsigned int size) -{ - if (!obj.isList()) - return false; - - if (obj.size() != size) { - LOG(Vector, Error) - << "Wrong number of values in YAML vector: expected " - << size << ", got " << obj.size(); - return false; - } - - return true; -} -#endif /* __DOXYGEN__ */ - -} /* namespace ipa */ - -} /* namespace libcamera */ diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h deleted file mode 100644 index fe33c9d6fbd1..000000000000 --- a/src/ipa/libipa/vector.h +++ /dev/null @@ -1,370 +0,0 @@ -/* 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 - -#include -#include - -#include "libcamera/internal/matrix.h" -#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 explicit Vector(T scalar) - { - data_.fill(scalar); - } - - constexpr Vector(const std::array &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]; - } - - 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 - { - return apply(*this, other, std::plus<>{}); - } - - constexpr Vector operator+(T scalar) const - { - return apply(*this, scalar, std::plus<>{}); - } - - constexpr Vector operator-(const Vector &other) const - { - return apply(*this, other, std::minus<>{}); - } - - constexpr Vector operator-(T scalar) const - { - return apply(*this, scalar, std::minus<>{}); - } - - constexpr Vector operator*(const Vector &other) const - { - return apply(*this, other, std::multiplies<>{}); - } - - constexpr Vector operator*(T scalar) const - { - return apply(*this, scalar, std::multiplies<>{}); - } - - constexpr Vector operator/(const Vector &other) const - { - return apply(*this, other, std::divides<>{}); - } - - constexpr Vector operator/(T scalar) const - { - return apply(*this, scalar, std::divides<>{}); - } - - Vector &operator+=(const Vector &other) - { - return apply(other, [](T a, T b) { return a + b; }); - } - - Vector &operator+=(T scalar) - { - return apply(scalar, [](T a, T b) { return a + b; }); - } - - Vector &operator-=(const Vector &other) - { - return apply(other, [](T a, T b) { return a - b; }); - } - - Vector &operator-=(T scalar) - { - return apply(scalar, [](T a, T b) { return a - b; }); - } - - Vector &operator*=(const Vector &other) - { - return apply(other, [](T a, T b) { return a * b; }); - } - - Vector &operator*=(T scalar) - { - return apply(scalar, [](T a, T b) { return a * b; }); - } - - Vector &operator/=(const Vector &other) - { - return apply(other, [](T a, T b) { return a / b; }); - } - - Vector &operator/=(T scalar) - { - return apply(scalar, [](T a, T b) { return a / b; }); - } - - constexpr Vector min(const Vector &other) const - { - return apply(*this, other, [](T a, T b) { return std::min(a, b); }); - } - - constexpr Vector min(T scalar) const - { - return apply(*this, scalar, [](T a, T b) { return std::min(a, b); }); - } - - constexpr Vector max(const Vector &other) const - { - return apply(*this, other, [](T a, T b) { return std::max(a, b); }); - } - - constexpr Vector max(T scalar) const - { - return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); }); - } - - constexpr T dot(const Vector &other) const - { - T ret = 0; - for (unsigned int i = 0; i < Rows; i++) - ret += data_[i] * other[i]; - return ret; - } - -#ifndef __DOXYGEN__ - template= 1>> -#endif /* __DOXYGEN__ */ - constexpr const T &x() const { return data_[0]; } -#ifndef __DOXYGEN__ - template= 2>> -#endif /* __DOXYGEN__ */ - constexpr const T &y() const { return data_[1]; } -#ifndef __DOXYGEN__ - template= 3>> -#endif /* __DOXYGEN__ */ - constexpr const T &z() const { return data_[2]; } -#ifndef __DOXYGEN__ - template= 1>> -#endif /* __DOXYGEN__ */ - constexpr T &x() { return data_[0]; } -#ifndef __DOXYGEN__ - template= 2>> -#endif /* __DOXYGEN__ */ - constexpr T &y() { return data_[1]; } -#ifndef __DOXYGEN__ - template= 3>> -#endif /* __DOXYGEN__ */ - constexpr T &z() { return data_[2]; } - -#ifndef __DOXYGEN__ - template= 1>> -#endif /* __DOXYGEN__ */ - constexpr const T &r() const { return data_[0]; } -#ifndef __DOXYGEN__ - template= 2>> -#endif /* __DOXYGEN__ */ - constexpr const T &g() const { return data_[1]; } -#ifndef __DOXYGEN__ - template= 3>> -#endif /* __DOXYGEN__ */ - constexpr const T &b() const { return data_[2]; } -#ifndef __DOXYGEN__ - template= 1>> -#endif /* __DOXYGEN__ */ - constexpr T &r() { return data_[0]; } -#ifndef __DOXYGEN__ - template= 2>> -#endif /* __DOXYGEN__ */ - constexpr T &g() { return data_[1]; } -#ifndef __DOXYGEN__ - template= 3>> -#endif /* __DOXYGEN__ */ - constexpr T &b() { return data_[2]; } - - 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()); - } - - template - constexpr R sum() const - { - return std::accumulate(data_.begin(), data_.end(), R{}); - } - -private: - template - static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) - { - Vector result; - std::transform(lhs.data_.begin(), lhs.data_.end(), - rhs.data_.begin(), result.data_.begin(), - op); - - return result; - } - - template - static constexpr Vector apply(const Vector &lhs, T rhs, BinaryOp op) - { - Vector result; - std::transform(lhs.data_.begin(), lhs.data_.end(), - result.data_.begin(), - [&op, rhs](T v) { return op(v, rhs); }); - - return result; - } - - template - Vector &apply(const Vector &other, BinaryOp op) - { - auto itOther = other.data_.begin(); - std::for_each(data_.begin(), data_.end(), - [&op, &itOther](T &v) { v = op(v, *itOther++); }); - - return *this; - } - - template - Vector &apply(T scalar, BinaryOp op) - { - std::for_each(data_.begin(), data_.end(), - [&op, scalar](T &v) { v = op(v, scalar); }); - - return *this; - } - - std::array data_; -}; - -template -using RGB = Vector; - -template -Vector operator*(const Matrix &m, const Vector &v) -{ - Vector 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 -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 */ diff --git a/test/ipa/libipa/meson.build b/test/ipa/libipa/meson.build index 0f4155d25b0c..eaf4b49a187c 100644 --- a/test/ipa/libipa/meson.build +++ b/test/ipa/libipa/meson.build @@ -3,7 +3,6 @@ libipa_test = [ {'name': 'fixedpoint', 'sources': ['fixedpoint.cpp']}, {'name': 'interpolator', 'sources': ['interpolator.cpp']}, - {'name': 'vector', 'sources': ['vector.cpp']}, ] foreach test : libipa_test diff --git a/test/ipa/libipa/vector.cpp b/test/ipa/libipa/vector.cpp deleted file mode 100644 index 8e4ec77d7820..000000000000 --- a/test/ipa/libipa/vector.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2024, Ideas on Board Oy - * - * Vector tests - */ - -#include "../src/ipa/libipa/vector.h" - -#include -#include - -#include "test.h" - -using namespace libcamera::ipa; - -#define ASSERT_EQ(a, b) \ -if ((a) != (b)) { \ - std::cout << #a " != " #b << " (line " << __LINE__ << ")" \ - << std::endl; \ - return TestFail; \ -} - -class VectorTest : public Test -{ -protected: - int run() - { - Vector v1{ 0.0 }; - - ASSERT_EQ(v1[0], 0.0); - ASSERT_EQ(v1[1], 0.0); - ASSERT_EQ(v1[2], 0.0); - - ASSERT_EQ(v1.length(), 0.0); - ASSERT_EQ(v1.length2(), 0.0); - - Vector v2{{ 1.0, 4.0, 8.0 }}; - - ASSERT_EQ(v2[0], 1.0); - ASSERT_EQ(v2[1], 4.0); - ASSERT_EQ(v2[2], 8.0); - - ASSERT_EQ(v2.x(), 1.0); - ASSERT_EQ(v2.y(), 4.0); - ASSERT_EQ(v2.z(), 8.0); - - ASSERT_EQ(v2.r(), 1.0); - ASSERT_EQ(v2.g(), 4.0); - ASSERT_EQ(v2.b(), 8.0); - - ASSERT_EQ(v2.length2(), 81.0); - ASSERT_EQ(v2.length(), 9.0); - ASSERT_EQ(v2.sum(), 13.0); - - Vector v3{ v2 }; - - ASSERT_EQ(v2, v3); - - v3 = Vector{{ 4.0, 4.0, 4.0 }}; - - ASSERT_EQ(v2 + v3, (Vector{{ 5.0, 8.0, 12.0 }})); - ASSERT_EQ(v2 + 4.0, (Vector{{ 5.0, 8.0, 12.0 }})); - ASSERT_EQ(v2 - v3, (Vector{{ -3.0, 0.0, 4.0 }})); - ASSERT_EQ(v2 - 4.0, (Vector{{ -3.0, 0.0, 4.0 }})); - ASSERT_EQ(v2 * v3, (Vector{{ 4.0, 16.0, 32.0 }})); - ASSERT_EQ(v2 * 4.0, (Vector{{ 4.0, 16.0, 32.0 }})); - ASSERT_EQ(v2 / v3, (Vector{{ 0.25, 1.0, 2.0 }})); - ASSERT_EQ(v2 / 4.0, (Vector{{ 0.25, 1.0, 2.0 }})); - - ASSERT_EQ(v2.min(v3), (Vector{{ 1.0, 4.0, 4.0 }})); - ASSERT_EQ(v2.min(4.0), (Vector{{ 1.0, 4.0, 4.0 }})); - ASSERT_EQ(v2.max(v3), (Vector{{ 4.0, 4.0, 8.0 }})); - ASSERT_EQ(v2.max(4.0), (Vector{{ 4.0, 4.0, 8.0 }})); - - ASSERT_EQ(v2.dot(v3), 52.0); - - v2 += v3; - ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); - v2 -= v3; - ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); - v2 *= v3; - ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); - v2 /= v3; - ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); - - v2 += 4.0; - ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); - v2 -= 4.0; - ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); - v2 *= 4.0; - ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); - v2 /= 4.0; - ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); - - return TestPass; - } -}; - -TEST_REGISTER(VectorTest)