From patchwork Sun Jun 21 00:23:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27005 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 E7E95C3302 for ; Sun, 21 Jun 2026 00:23:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C9219656F7; Sun, 21 Jun 2026 02:23:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="sxX2dxj0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6FB12656DE for ; Sun, 21 Jun 2026 02:23:08 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8AFDA268; Sun, 21 Jun 2026 02:22:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782001351; bh=gRlSLhz/FUmkmd9f1DoYgigUOm4rFF5B4LHC0MVmD5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sxX2dxj05MduNlGKU/dKatRyeE5yBWE4CT4TrBy7AjWzaYn1sDLeOuzX+utiF2lGI 6Y51vQDFvzBErSkCF+mtcJitI7XrI1g608gj8BOeQYDfyLezVYH7FCRmPdUviFyZXQ JpFY7ya7iuDnSKtHOgzNsH3zss7/MFd7K6Qv8w6k= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham Subject: [PATCH 1/4] libcamera: vector: Replace class with typename Date: Sun, 21 Jun 2026 03:23:02 +0300 Message-ID: <20260621002305.3763752-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260621002305.3763752-1-laurent.pinchart@ideasonboard.com> References: <20260621002305.3763752-1-laurent.pinchart@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" libcamera uses "typename" instead of "class" to denote template parameter types. The vector class uses the latter, replace them with "typename" for consistency. Signed-off-by: Laurent Pinchart --- include/libcamera/internal/vector.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h index 093efafa8982..04ba5d847b7d 100644 --- a/include/libcamera/internal/vector.h +++ b/include/libcamera/internal/vector.h @@ -263,7 +263,7 @@ public: } private: - template + template static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) { Vector result; @@ -274,7 +274,7 @@ private: return result; } - template + template static constexpr Vector apply(const Vector &lhs, U rhs, BinaryOp op) { Vector result; @@ -285,7 +285,7 @@ private: return result; } - template + template Vector &apply(const Vector &other, BinaryOp op) { auto itOther = other.data_.begin(); @@ -295,7 +295,7 @@ private: return *this; } - template + template Vector &apply(U scalar, BinaryOp op) { std::for_each(data_.begin(), data_.end(), From patchwork Sun Jun 21 00:23:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27006 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 DEE01C3305 for ; Sun, 21 Jun 2026 00:23:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 25FF0656E9; Sun, 21 Jun 2026 02:23:14 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="TDXV6XVW"; 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 DC3C9656E5 for ; Sun, 21 Jun 2026 02:23:09 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 05975268; Sun, 21 Jun 2026 02:22:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782001353; bh=MHe02q6CXE8PDIJbA2P3DGADl8LDSW7CvfPNOr4bwOY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TDXV6XVWm8lL7JQa6OJAun/P0zYGTednOxBGxaza6fVciQD36UM1Ka04S0N+xh8RY PG4y+qDBbjVwGenZMFMAhfKb2X9YHh7gjBTOuxbqTUCVIj1q3Ud+IgnkyU6uvUbQhq hVNxYtfzRESErehJkeA2ZU4QSneu1dks5x3/nz3U= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham Subject: [PATCH 2/4] libcamera: vector: Swap order of arguments to apply() Date: Sun, 21 Jun 2026 03:23:03 +0300 Message-ID: <20260621002305.3763752-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260621002305.3763752-1-laurent.pinchart@ideasonboard.com> References: <20260621002305.3763752-1-laurent.pinchart@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 is lacking a clamp() function, which will take two scalar parameters. To support that, the apply() function will need to be converted to variable number of parameters. This will require passing the scalar parameter last, to make automatic template arguments deduction possible. In preparation for that change, swap the arguments to apply() to pass the operation before the scalar parameter last. Only one variant of apply() strictly requires this change, arguments to the three other functions are also swapped for consistency. Also for consistency, swap the template arguments as well. Signed-off-by: Laurent Pinchart --- include/libcamera/internal/vector.h | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h index 04ba5d847b7d..256de1d1c53a 100644 --- a/include/libcamera/internal/vector.h +++ b/include/libcamera/internal/vector.h @@ -73,116 +73,116 @@ public: constexpr Vector operator+(const Vector &other) const { - return apply(*this, other, std::plus<>{}); + return apply(*this, std::plus<>{}, other); } constexpr Vector operator+(T scalar) const { - return apply(*this, scalar, std::plus<>{}); + return apply(*this, std::plus<>{}, scalar); } constexpr Vector operator-(const Vector &other) const { - return apply(*this, other, std::minus<>{}); + return apply(*this, std::minus<>{}, other); } constexpr Vector operator-(T scalar) const { - return apply(*this, scalar, std::minus<>{}); + return apply(*this, std::minus<>{}, scalar); } constexpr Vector operator*(const Vector &other) const { - return apply(*this, other, std::multiplies<>{}); + return apply(*this, std::multiplies<>{}, other); } constexpr Vector operator*(T scalar) const { - return apply(*this, scalar, std::multiplies<>{}); + return apply(*this, std::multiplies<>{}, scalar); } constexpr Vector operator/(const Vector &other) const { - return apply(*this, other, std::divides<>{}); + return apply(*this, std::divides<>{}, other); } constexpr Vector operator/(T scalar) const { - return apply(*this, scalar, std::divides<>{}); + return apply(*this, std::divides<>{}, scalar); } constexpr Vector operator>>(unsigned int shift) const { static_assert(std::is_integral_v, "Vector::operator>> requires an integer element type"); - return apply(*this, shift, [](T a, unsigned int b) { return a >> b; }); + return apply(*this, [](T a, unsigned int b) { return a >> b; }, shift); } Vector &operator+=(const Vector &other) { - return apply(other, [](T a, T b) { return a + b; }); + return apply([](T a, T b) { return a + b; }, other); } Vector &operator+=(T scalar) { - return apply(scalar, [](T a, T b) { return a + b; }); + return apply([](T a, T b) { return a + b; }, scalar); } Vector &operator-=(const Vector &other) { - return apply(other, [](T a, T b) { return a - b; }); + return apply([](T a, T b) { return a - b; }, other); } Vector &operator-=(T scalar) { - return apply(scalar, [](T a, T b) { return a - b; }); + return apply([](T a, T b) { return a - b; }, scalar); } Vector &operator*=(const Vector &other) { - return apply(other, [](T a, T b) { return a * b; }); + return apply([](T a, T b) { return a * b; }, other); } Vector &operator*=(T scalar) { - return apply(scalar, [](T a, T b) { return a * b; }); + return apply([](T a, T b) { return a * b; }, scalar); } Vector &operator/=(const Vector &other) { - return apply(other, [](T a, T b) { return a / b; }); + return apply([](T a, T b) { return a / b; }, other); } Vector &operator/=(T scalar) { - return apply(scalar, [](T a, T b) { return a / b; }); + return apply([](T a, T b) { return a / b; }, scalar); } Vector &operator>>=(unsigned int shift) { static_assert(std::is_integral_v, "Vector::operator>>= requires an integer element type"); - return apply(shift, [](T a, unsigned int b) { return a >> b; }); + return apply([](T a, unsigned int b) { return a >> b; }, shift); } constexpr Vector min(const Vector &other) const { - return apply(*this, other, [](T a, T b) { return std::min(a, b); }); + return apply(*this, [](T a, T b) { return std::min(a, b); }, other); } constexpr Vector min(T scalar) const { - return apply(*this, scalar, [](T a, T b) { return std::min(a, b); }); + return apply(*this, [](T a, T b) { return std::min(a, b); }, scalar); } constexpr Vector max(const Vector &other) const { - return apply(*this, other, [](T a, T b) { return std::max(a, b); }); + return apply(*this, [](T a, T b) { return std::max(a, b); }, other); } constexpr Vector max(T scalar) const { - return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); }); + return apply(*this, [](T a, T b) -> T { return std::max(a, b); }, scalar); } constexpr T dot(const Vector &other) const @@ -264,7 +264,7 @@ public: private: template - static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) + static constexpr Vector apply(const Vector &lhs, BinaryOp op, const Vector &rhs) { Vector result; std::transform(lhs.data_.begin(), lhs.data_.end(), @@ -274,8 +274,8 @@ private: return result; } - template - static constexpr Vector apply(const Vector &lhs, U rhs, BinaryOp op) + template + static constexpr Vector apply(const Vector &lhs, BinaryOp op, U rhs) { Vector result; std::transform(lhs.data_.begin(), lhs.data_.end(), @@ -286,7 +286,7 @@ private: } template - Vector &apply(const Vector &other, BinaryOp op) + Vector &apply(BinaryOp op, const Vector &other) { auto itOther = other.data_.begin(); std::for_each(data_.begin(), data_.end(), @@ -295,8 +295,8 @@ private: return *this; } - template - Vector &apply(U scalar, BinaryOp op) + template + Vector &apply(BinaryOp op, U scalar) { std::for_each(data_.begin(), data_.end(), [&op, scalar](T &v) { v = op(v, scalar); }); From patchwork Sun Jun 21 00:23:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27007 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 9116CC3306 for ; Sun, 21 Jun 2026 00:23:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 06B0A656E5; Sun, 21 Jun 2026 02:23:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XRQ3XkX4"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F1BAD656E9 for ; Sun, 21 Jun 2026 02:23:11 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 84E6AB8B; Sun, 21 Jun 2026 02:22:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782001354; bh=0WMvP4YZu3wStzAx0c8cs6xCUyzGowBc//PCpN3eih8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XRQ3XkX4zwJi1N+IDqAOwDVlRM7xrUg0Pc/mSbiU9Q1QtUCVxHU4G5M61F0lVt8uH xZgejhoi1Au50rUU2zTryjPWMM+imO6omNIwYRsnjDu7GRUUg+MYp3P8wVIUNGOWJf p71W/riGIPKNUV0ky624MV3UVo70yxZQJNP62cio= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham Subject: [PATCH 3/4] libcamera: vector: Support multiple scalar arguments to apply() Date: Sun, 21 Jun 2026 03:23:04 +0300 Message-ID: <20260621002305.3763752-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260621002305.3763752-1-laurent.pinchart@ideasonboard.com> References: <20260621002305.3763752-1-laurent.pinchart@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" In preparation for the addition of a clamp() function to the vector class, extend the apply() function to support multiple scalar arguments. Signed-off-by: Laurent Pinchart --- include/libcamera/internal/vector.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h index 256de1d1c53a..7c90d6542352 100644 --- a/include/libcamera/internal/vector.h +++ b/include/libcamera/internal/vector.h @@ -274,13 +274,13 @@ private: return result; } - template - static constexpr Vector apply(const Vector &lhs, BinaryOp op, U rhs) + template + static constexpr Vector apply(const Vector &vector, Op op, U... scalar) { Vector result; - std::transform(lhs.data_.begin(), lhs.data_.end(), + std::transform(vector.data_.begin(), vector.data_.end(), result.data_.begin(), - [&op, rhs](T v) { return op(v, rhs); }); + [&op, scalar...](T v) { return op(v, scalar...); }); return result; } @@ -295,11 +295,11 @@ private: return *this; } - template - Vector &apply(BinaryOp op, U scalar) + template + Vector &apply(Op op, U... scalar) { std::for_each(data_.begin(), data_.end(), - [&op, scalar](T &v) { v = op(v, scalar); }); + [&op, scalar...](T &v) { v = op(v, scalar...); }); return *this; } From patchwork Sun Jun 21 00:23:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 27008 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 5EB84C3307 for ; Sun, 21 Jun 2026 00:23:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D6439656F4; Sun, 21 Jun 2026 02:23:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ULA9vr5u"; 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 E4329656E5 for ; Sun, 21 Jun 2026 02:23:12 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1056E268; Sun, 21 Jun 2026 02:22:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1782001356; bh=sw9YqKgDYcqB85sXmuOJ+W8a6HWiz4GDP0cDtZxX6t8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ULA9vr5u9S6CSuuzzwq9DbeMtUzgQ1qQF1DmUaTbBn64AmL/TotseYhl6oR0W3SeX 2HAsHjEmhasWXnAZl9ZS6erfcGb1YTi7tEN2nZ2/eUdjrtmKNbuZI9EXW+XsDS6xxW zbmmhBSCGGRYqrHRoozZK6oGItGef8WkaZYqv5Qk= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham Subject: [PATCH 4/4] libcamera: vector: Add clamp() member function Date: Sun, 21 Jun 2026 03:23:05 +0300 Message-ID: <20260621002305.3763752-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260621002305.3763752-1-laurent.pinchart@ideasonboard.com> References: <20260621002305.3763752-1-laurent.pinchart@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" From: Kieran Bingham Provide a member function that performs a std::clamp() given a scalar high and low values to clamp to. Suggested-by: Laurent Pinchart Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- Changes since Kieran's version: - Use apply() - Fix typos in commit message --- include/libcamera/internal/vector.h | 7 +++++++ src/libcamera/vector.cpp | 8 ++++++++ test/vector.cpp | 1 + 3 files changed, 16 insertions(+) diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h index 7c90d6542352..0270651a0ef7 100644 --- a/include/libcamera/internal/vector.h +++ b/include/libcamera/internal/vector.h @@ -185,6 +185,13 @@ public: return apply(*this, [](T a, T b) -> T { return std::max(a, b); }, scalar); } + constexpr Vector clamp(T low, T high) const + { + return apply(*this, + [](T v, T lo, T hi) -> T { return std::clamp(v, lo, hi); }, + low, high); + } + constexpr T dot(const Vector &other) const { T ret = 0; diff --git a/src/libcamera/vector.cpp b/src/libcamera/vector.cpp index 47b3d1af36d9..a135ab498e17 100644 --- a/src/libcamera/vector.cpp +++ b/src/libcamera/vector.cpp @@ -224,6 +224,14 @@ LOG_DEFINE_CATEGORY(Vector) * \return The element-wise maximum of this vector and \a scalar */ +/** + * \fn Vector::clamp(T low, T high) const + * \brief Clamp the vector element-wise between \a low and \a high + * \param[in] low The lower limit + * \param[in] high The upper limit + * \return A vector with each element clamped between \a low and \a high + */ + /** * \fn Vector::dot(const Vector &other) const * \brief Compute the dot product diff --git a/test/vector.cpp b/test/vector.cpp index 4ff908e8f682..2f3d97d93dcc 100644 --- a/test/vector.cpp +++ b/test/vector.cpp @@ -72,6 +72,7 @@ protected: 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.clamp(2.0, 6.0), (Vector{{ 2.0, 4.0, 6.0 }})); ASSERT_EQ(v2.dot(v3), 52.0);