[v3,06/17] ipa: libipa: vector: Generalize arithmetic operators
diff mbox series

Message ID 20241118221618.13953-7-laurent.pinchart@ideasonboard.com
State New
Headers show
Series
  • Improve linear algebra helpers in libipa
Related show

Commit Message

Laurent Pinchart Nov. 18, 2024, 10:16 p.m. UTC
Instead of hand-coding all arithmetic operators, implement them based on
a generic apply() function that takes an operator-specific
std::function. This will simplify adding missing arithmetic operators.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
---
Changes since v2:

- Include <algorithm>
- Use std::plus, std::minus, std::multiplies and std::divides
---
 src/ipa/libipa/vector.h | 50 ++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 20 deletions(-)

Comments

Barnabás Pőcze Nov. 18, 2024, 11:40 p.m. UTC | #1
Hi


2024. november 18., hétfő 23:16 keltezéssel, Laurent Pinchart <laurent.pinchart@ideasonboard.com> írta:

> Instead of hand-coding all arithmetic operators, implement them based on
> a generic apply() function that takes an operator-specific
> std::function. This will simplify adding missing arithmetic operators.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
> ---
> Changes since v2:
> 
> - Include <algorithm>
> - Use std::plus, std::minus, std::multiplies and std::divides
> ---
>  src/ipa/libipa/vector.h | 50 ++++++++++++++++++++++++-----------------
>  1 file changed, 30 insertions(+), 20 deletions(-)
> 
> diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h
> index 2abb5536361c..76fd2934b870 100644
> --- a/src/ipa/libipa/vector.h
> +++ b/src/ipa/libipa/vector.h
> @@ -6,8 +6,10 @@
>   */
>  #pragma once
> 
> +#include <algorithm>
>  #include <array>
>  #include <cmath>
> +#include <functional>
>  #include <optional>
>  #include <ostream>
> 
> @@ -78,36 +80,24 @@ public:
>  		return ret;
>  	}
> 
> -	constexpr Vector<T, Rows> operator-(const Vector<T, Rows> &other) const
> +	constexpr Vector operator-(const Vector &other) const
>  	{
> -		Vector<T, Rows> ret;
> -		for (unsigned int i = 0; i < Rows; i++)
> -			ret[i] = data_[i] - other[i];
> -		return ret;
> +		return apply(*this, other, std::minus<>{});
>  	}
> 
> -	constexpr Vector<T, Rows> operator+(const Vector<T, Rows> &other) const
> +	constexpr Vector operator+(const Vector &other) const
>  	{
> -		Vector<T, Rows> ret;
> -		for (unsigned int i = 0; i < Rows; i++)
> -			ret[i] = data_[i] + other[i];
> -		return ret;
> +		return apply(*this, other, std::plus<>{});
>  	}
> 
> -	constexpr Vector<T, Rows> operator*(T factor) const
> +	constexpr Vector operator*(T factor) const
>  	{
> -		Vector<T, Rows> ret;
> -		for (unsigned int i = 0; i < Rows; i++)
> -			ret[i] = data_[i] * factor;
> -		return ret;
> +		return apply(*this, factor, std::multiplies<>{});
>  	}
> 
> -	constexpr Vector<T, Rows> operator/(T factor) const
> +	constexpr Vector operator/(T factor) const
>  	{
> -		Vector<T, Rows> ret;
> -		for (unsigned int i = 0; i < Rows; i++)
> -			ret[i] = data_[i] / factor;
> -		return ret;
> +		return apply(*this, factor, std::divides<>{});
>  	}
> 
>  	constexpr T dot(const Vector<T, Rows> &other) const
> @@ -182,6 +172,26 @@ public:
>  	}
> 
>  private:
> +	static constexpr Vector apply(const Vector &lhs, const Vector &rhs, std::function<T(T, T)> func)
> +	{
> +		Vector result;
> +		std::transform(lhs.data_.begin(), lhs.data_.end(),
> +			       rhs.data_.begin(), result.data_.begin(),
> +			       func);
> +
> +		return result;
> +	}
> +
> +	static constexpr Vector apply(const Vector &lhs, T rhs, std::function<T(T, T)> func)
> +	{
> +		Vector result;
> +		std::transform(lhs.data_.begin(), lhs.data_.end(),
> +			       result.data_.begin(),
> +			       [&func, rhs](T v) { return func(v, rhs); });
> +
> +		return result;
> +	}

`std::function` is quite heavy. I think making `apply()` a template would be
beneficial wrt. performance.


Regards,
Barnabás Pőcze

> +
>  	std::array<T, Rows> data_;
>  };
> 
> --
> Regards,
> 
> Laurent Pinchart
Laurent Pinchart Nov. 19, 2024, 8:39 a.m. UTC | #2
Hi Barnabás,

On Mon, Nov 18, 2024 at 11:40:16PM +0000, Barnabás Pőcze wrote:
> 2024. november 18., hétfő 23:16 keltezéssel, Laurent Pinchart írta:
> 
> > Instead of hand-coding all arithmetic operators, implement them based on
> > a generic apply() function that takes an operator-specific
> > std::function. This will simplify adding missing arithmetic operators.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
> > ---
> > Changes since v2:
> > 
> > - Include <algorithm>
> > - Use std::plus, std::minus, std::multiplies and std::divides
> > ---
> >  src/ipa/libipa/vector.h | 50 ++++++++++++++++++++++++-----------------
> >  1 file changed, 30 insertions(+), 20 deletions(-)
> > 
> > diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h
> > index 2abb5536361c..76fd2934b870 100644
> > --- a/src/ipa/libipa/vector.h
> > +++ b/src/ipa/libipa/vector.h
> > @@ -6,8 +6,10 @@
> >   */
> >  #pragma once
> > 
> > +#include <algorithm>
> >  #include <array>
> >  #include <cmath>
> > +#include <functional>
> >  #include <optional>
> >  #include <ostream>
> > 
> > @@ -78,36 +80,24 @@ public:
> >  		return ret;
> >  	}
> > 
> > -	constexpr Vector<T, Rows> operator-(const Vector<T, Rows> &other) const
> > +	constexpr Vector operator-(const Vector &other) const
> >  	{
> > -		Vector<T, Rows> ret;
> > -		for (unsigned int i = 0; i < Rows; i++)
> > -			ret[i] = data_[i] - other[i];
> > -		return ret;
> > +		return apply(*this, other, std::minus<>{});
> >  	}
> > 
> > -	constexpr Vector<T, Rows> operator+(const Vector<T, Rows> &other) const
> > +	constexpr Vector operator+(const Vector &other) const
> >  	{
> > -		Vector<T, Rows> ret;
> > -		for (unsigned int i = 0; i < Rows; i++)
> > -			ret[i] = data_[i] + other[i];
> > -		return ret;
> > +		return apply(*this, other, std::plus<>{});
> >  	}
> > 
> > -	constexpr Vector<T, Rows> operator*(T factor) const
> > +	constexpr Vector operator*(T factor) const
> >  	{
> > -		Vector<T, Rows> ret;
> > -		for (unsigned int i = 0; i < Rows; i++)
> > -			ret[i] = data_[i] * factor;
> > -		return ret;
> > +		return apply(*this, factor, std::multiplies<>{});
> >  	}
> > 
> > -	constexpr Vector<T, Rows> operator/(T factor) const
> > +	constexpr Vector operator/(T factor) const
> >  	{
> > -		Vector<T, Rows> ret;
> > -		for (unsigned int i = 0; i < Rows; i++)
> > -			ret[i] = data_[i] / factor;
> > -		return ret;
> > +		return apply(*this, factor, std::divides<>{});
> >  	}
> > 
> >  	constexpr T dot(const Vector<T, Rows> &other) const
> > @@ -182,6 +172,26 @@ public:
> >  	}
> > 
> >  private:
> > +	static constexpr Vector apply(const Vector &lhs, const Vector &rhs, std::function<T(T, T)> func)
> > +	{
> > +		Vector result;
> > +		std::transform(lhs.data_.begin(), lhs.data_.end(),
> > +			       rhs.data_.begin(), result.data_.begin(),
> > +			       func);
> > +
> > +		return result;
> > +	}
> > +
> > +	static constexpr Vector apply(const Vector &lhs, T rhs, std::function<T(T, T)> func)
> > +	{
> > +		Vector result;
> > +		std::transform(lhs.data_.begin(), lhs.data_.end(),
> > +			       result.data_.begin(),
> > +			       [&func, rhs](T v) { return func(v, rhs); });
> > +
> > +		return result;
> > +	}
> 
> `std::function` is quite heavy. I think making `apply()` a template would be
> beneficial wrt. performance.

I'll try it out in v4.

> > +
> >  	std::array<T, Rows> data_;
> >  };
> >

Patch
diff mbox series

diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h
index 2abb5536361c..76fd2934b870 100644
--- a/src/ipa/libipa/vector.h
+++ b/src/ipa/libipa/vector.h
@@ -6,8 +6,10 @@ 
  */
 #pragma once
 
+#include <algorithm>
 #include <array>
 #include <cmath>
+#include <functional>
 #include <optional>
 #include <ostream>
 
@@ -78,36 +80,24 @@  public:
 		return ret;
 	}
 
-	constexpr Vector<T, Rows> operator-(const Vector<T, Rows> &other) const
+	constexpr Vector operator-(const Vector &other) const
 	{
-		Vector<T, Rows> ret;
-		for (unsigned int i = 0; i < Rows; i++)
-			ret[i] = data_[i] - other[i];
-		return ret;
+		return apply(*this, other, std::minus<>{});
 	}
 
-	constexpr Vector<T, Rows> operator+(const Vector<T, Rows> &other) const
+	constexpr Vector operator+(const Vector &other) const
 	{
-		Vector<T, Rows> ret;
-		for (unsigned int i = 0; i < Rows; i++)
-			ret[i] = data_[i] + other[i];
-		return ret;
+		return apply(*this, other, std::plus<>{});
 	}
 
-	constexpr Vector<T, Rows> operator*(T factor) const
+	constexpr Vector operator*(T factor) const
 	{
-		Vector<T, Rows> ret;
-		for (unsigned int i = 0; i < Rows; i++)
-			ret[i] = data_[i] * factor;
-		return ret;
+		return apply(*this, factor, std::multiplies<>{});
 	}
 
-	constexpr Vector<T, Rows> operator/(T factor) const
+	constexpr Vector operator/(T factor) const
 	{
-		Vector<T, Rows> ret;
-		for (unsigned int i = 0; i < Rows; i++)
-			ret[i] = data_[i] / factor;
-		return ret;
+		return apply(*this, factor, std::divides<>{});
 	}
 
 	constexpr T dot(const Vector<T, Rows> &other) const
@@ -182,6 +172,26 @@  public:
 	}
 
 private:
+	static constexpr Vector apply(const Vector &lhs, const Vector &rhs, std::function<T(T, T)> func)
+	{
+		Vector result;
+		std::transform(lhs.data_.begin(), lhs.data_.end(),
+			       rhs.data_.begin(), result.data_.begin(),
+			       func);
+
+		return result;
+	}
+
+	static constexpr Vector apply(const Vector &lhs, T rhs, std::function<T(T, T)> func)
+	{
+		Vector result;
+		std::transform(lhs.data_.begin(), lhs.data_.end(),
+			       result.data_.begin(),
+			       [&func, rhs](T v) { return func(v, rhs); });
+
+		return result;
+	}
+
 	std::array<T, Rows> data_;
 };