[1/7] libcamera: vector: Add clamp operation
diff mbox series

Message ID 20260621-kbingham-awb-saturation-v1-1-b91ea59c6cfb@ideasonboard.com
State New
Headers show
Series
  • softisp: Fix Saturation and Black level handling
Related show

Commit Message

Kieran Bingham June 20, 2026, 11 p.m. UTC
Provide a helper that will perform a std::clamp given a scaler high and
low value to clamp to.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 include/libcamera/internal/vector.h | 8 ++++++++
 src/libcamera/vector.cpp            | 8 ++++++++
 test/vector.cpp                     | 1 +
 3 files changed, 17 insertions(+)

Comments

Laurent Pinchart June 21, 2026, 12:19 a.m. UTC | #1
Hi Kieran,

Thank you for the patch.

On Sun, Jun 21, 2026 at 12:00:28AM +0100, Kieran Bingham wrote:
> Provide a helper that will perform a std::clamp given a scaler high and
> low value to clamp to.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>  include/libcamera/internal/vector.h | 8 ++++++++
>  src/libcamera/vector.cpp            | 8 ++++++++
>  test/vector.cpp                     | 1 +
>  3 files changed, 17 insertions(+)
> 
> diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h
> index 093efafa8982fe553a953316ac794bef46eec5d4..17ecbda50f2dc4363548a4a29639a751a187dac6 100644
> --- a/include/libcamera/internal/vector.h
> +++ b/include/libcamera/internal/vector.h
> @@ -185,6 +185,14 @@ public:
>  		return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); });
>  	}
>  
> +	constexpr Vector clamp(T low, T high) const
> +	{
> +		Vector result;
> +		for (unsigned int i = 0; i < Rows; i++)
> +			result[i] = std::clamp(data_[i], low, high);

I toyed with the idea of replacing

	template<class U, class BinaryOp>
	static constexpr Vector apply(const Vector &lhs, U rhs, BinaryOp op)

with

	template<class U..., class BinaryOp>
	static constexpr Vector apply(const Vector &lhs, U... rhs, BinaryOp op)

Patch series coming soon.

> +		return result;
> +	}
> +
>  	constexpr T dot(const Vector<T, Rows> &other) const
>  	{
>  		T ret = 0;
> diff --git a/src/libcamera/vector.cpp b/src/libcamera/vector.cpp
> index 47b3d1af36d90f9719c527b8458fbfe07412239e..a135ab498e17149b9dc54de7204e8a34262a2da9 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<T, Rows> &other) const
>   * \brief Compute the dot product
> diff --git a/test/vector.cpp b/test/vector.cpp
> index 4ff908e8f682f19d65c55d071fcd300071cf90ac..2f3d97d93dccbe153f2d1cf536423f7446a22aab 100644
> --- a/test/vector.cpp
> +++ b/test/vector.cpp
> @@ -72,6 +72,7 @@ protected:
>  		ASSERT_EQ(v2.min(4.0), (Vector<double, 3>{{ 1.0, 4.0, 4.0 }}));
>  		ASSERT_EQ(v2.max(v3), (Vector<double, 3>{{ 4.0, 4.0, 8.0 }}));
>  		ASSERT_EQ(v2.max(4.0), (Vector<double, 3>{{ 4.0, 4.0, 8.0 }}));
> +		ASSERT_EQ(v2.clamp(2.0, 6.0), (Vector<double, 3>{{ 2.0, 4.0, 6.0 }}));
>  
>  		ASSERT_EQ(v2.dot(v3), 52.0);
>

Patch
diff mbox series

diff --git a/include/libcamera/internal/vector.h b/include/libcamera/internal/vector.h
index 093efafa8982fe553a953316ac794bef46eec5d4..17ecbda50f2dc4363548a4a29639a751a187dac6 100644
--- a/include/libcamera/internal/vector.h
+++ b/include/libcamera/internal/vector.h
@@ -185,6 +185,14 @@  public:
 		return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); });
 	}
 
+	constexpr Vector clamp(T low, T high) const
+	{
+		Vector result;
+		for (unsigned int i = 0; i < Rows; i++)
+			result[i] = std::clamp(data_[i], low, high);
+		return result;
+	}
+
 	constexpr T dot(const Vector<T, Rows> &other) const
 	{
 		T ret = 0;
diff --git a/src/libcamera/vector.cpp b/src/libcamera/vector.cpp
index 47b3d1af36d90f9719c527b8458fbfe07412239e..a135ab498e17149b9dc54de7204e8a34262a2da9 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<T, Rows> &other) const
  * \brief Compute the dot product
diff --git a/test/vector.cpp b/test/vector.cpp
index 4ff908e8f682f19d65c55d071fcd300071cf90ac..2f3d97d93dccbe153f2d1cf536423f7446a22aab 100644
--- a/test/vector.cpp
+++ b/test/vector.cpp
@@ -72,6 +72,7 @@  protected:
 		ASSERT_EQ(v2.min(4.0), (Vector<double, 3>{{ 1.0, 4.0, 4.0 }}));
 		ASSERT_EQ(v2.max(v3), (Vector<double, 3>{{ 4.0, 4.0, 8.0 }}));
 		ASSERT_EQ(v2.max(4.0), (Vector<double, 3>{{ 4.0, 4.0, 8.0 }}));
+		ASSERT_EQ(v2.clamp(2.0, 6.0), (Vector<double, 3>{{ 2.0, 4.0, 6.0 }}));
 
 		ASSERT_EQ(v2.dot(v3), 52.0);